// ==UserScript==
// @name           villagePreviewEnhancer aka Piękny Widok.
// @namespace      dev::
// @description    brak opisu
// @version        1.3.0209 BETA
// @include        http://pl*.plemiona.pl/game.php*
// @license        Creative Commons 2.5 BY-NC-SA (http://creativecommons.org/licenses/by-nc-sa/2.5/pl)
// @author         Nexces
// @contributor    Debren
// ==/UserScript==
// ------------------------------------------------------------------------------------------------------------------------
//
// Thanks to Zombie74 for inspiration and for very nice color palette function. (:
// Keep up the good work m8!
//
// Thanks to Debren for creating dataset with different world settings and all those other little things i can't remember
//
// Thanks to RafałeQ for hint on finding solution to sorting problem
//
// ------------------------------------------------------------------------------------------------------------------------
//
// ChangeLog
//
// 1.3.1.0209 (publication date: 13/05/2009 14:33)
// (*) Preview screen: sorting fix (works on dataset) by Debren (initial idea by RafałeQ)
// (*) Preview screen: BB link fixed
// (*) Header: Nobelman information will not be displayed as last item if there is an ongoing attack
// (*) Internal: updated version history
// (*) Internal: UCL update for Opera
//
// 1.3.1.0207 (publication date: 12/05/2009 12:07)
// (+) Preview screen: sorting for non PA users
// (+) Preview screen: Plain text and BB list of displayed villages
//
// 1.3.1.0205 (publication date: 11/05/2009 13:56)
// (*) Preview screen: fixed sorting. (numbers are no longer fractions)
// (*) Internal: fixed version number in settings :P
// (*) Internal: fixed loader address
//
// 1.3.1.0202 (publication date: 10/05/2009 17:11)
// (+) Preview screen: sorting via: points, loyalty, resources, storage, workers, coins/packages, build queue
// (+) Preview screen: highlight current village
// (*) Internal: Fixed header and villages list detection (should prevent replacing other tables)
//
// 1.3.1.0199 (publication date: 08/05/2009 21:05)
// (+) Preview screen: number of displayed villages
// (+) Preview screen: summed points of displayed villages
// (*) Preview screen: hidding columns (with frackin' IE7Fix!)
// (*) Preview screen: rounded corners for IE7 have finally arived!
// (*) Internal: recreate settings for different worlds (by Debren)
// (*) Preview screen: fix loyalty calculation for worlds with other setting
// (*) Preview screen: fix image selection for worlds with package for snob instead of coins
// (+) Settings screen: resources alert color selection
// (*) fix missing settings representation
// (&) versioning system change
//
// 1.3.0190 (publication date: 08/05/2009)
// (+) initial, marked as stable, release
//
// (+) - added, (-) removed, (*) - fixed; (&) - comment
// ------------------------------------------------------------------------------------------------------------------------
//
// Known issues (which won't be fixed in 1.3.1 line):
// > Google Chrome can make sorting difficult
// > Internet Explorer 8 and probably whole line of IE have problems with string comparison (sorting problem)
// > Internet Explorer 8 and probably whole line of IE doesn't know how to apply CSS float to PRE tag so BB List will
//   produce some rather strange lists on this browsers
// > There are some account sitting issues (probably limited to nobelman extensions)
// > Script is slow
//
// ------------------------------------------------------------------------------------------------------------------------
//
// Variables listing:
//
// imageResourcesAddress
// worldSettings
// versionString
//
// private:
// initDone
// storedHeaderWood
// storedHeaderClay
// storedHeaderIron
// configLoaded
// standardColorPalette <= marked for removal
// resourcesColorPalette <= marked for removal
// resourcesAlertColorPalette <= marked for removal
// standardColorPaletteFilled <= marked for removal
// resourcesColorPaletteFilled <= marked for removal
// resourcesAlertColorPaletteFilled <= marked for removal
// loyaltyData
// loyaltyDataLoaded
// settings
// settingsEmpty
// sortedBy
// sortingInProgress
//
// images:
// CUL
// CUR
// CDL
// CDR
//
//
// Functions listing:
//
// init()
//
// display modification functions:
// loadSettings()
// loadDynamicMenuLink()
// loadHeader()
// headerWoodUpdater()
// headerClayUpdater()
// headerIronUpdater()
// headerWorkers()
// headerSnob()
// loadProduction()
// sortProduction()
// displayAsBB()
//
// background update functions:
// headerUpdater()
// flashWorkersOverfill()
//
// data colectors:
// loyaltyScan()
// getWorld()
// getWorldId()
// getURL()
// getWood()
// getClay()
// getIron()
// getStorage()
// getWorkers()
// getVillageId()
// getOverviewMode()
// isPA()
//
// raw cookie parsers:
// setValue()
// getValue()
//
// cookie helpers:
// setLoyalty()
// getLoyalty()
// loadConfigData()
// storeSettings()
//
// helpers:
// configGet()
// calcPack()
// calcSnob()
//
// configFormWorkersNeutralizationActivator()
// getWorldSetting()
//
// used internaly by JS:
//
//
// those probably could be merged into one...
// fillResourcesAlertColorTable()
// fillResourcesColorTable()
// fillStandardColorTable()
//
//
// conclusion: huge but effective... and probabaly defective... whatever...
// ------------------------------------------------------------------------------------------------------------------------




if ((typeof unsafeWindow) == "undefined") {
	unsafeWindow = window;
}
String.prototype.htmlentities = function () {
	return this.replace(/</g,'&lt;').replace(/>/g,'&gt;');
}
unsafeWindow.villagePreviewEnhancer = {
	/* user config section */
	imageResourcesAddress : 'http://plemiona-skrypty.googlecode.com/svn/testowe/villagePreviewEnhancer/images/',
	worldSettings : {
		snobType : ["gold", "res"],
		packPrice : [[28000,30000,25000], [20000,30000,25000]],
		snobPrice: [[40000,50000,50000],[28000,30000,25000],[20000,30000,25000]],
		loyaltyPerHour: [1,1.6,2],
		worldset : [
					[1,1,2,0],
					[1,1,1,0],[1,1,1,0],[0,0,0,0],[0,0,0,0],[0,0,0,0], [0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[1,1,1,2],
					[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[1,1,1,0], [0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],
					[1,1,1,0],[0,0,0,0],[1,1,1,2],[1,1,2,0],[0,0,0,0], [0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,1],[0,0,0,0],
					[0,0,0,0],[0,0,0,2],[0,0,0,0]
				]

	},
	versionString : '1.3.1.0209 BETA (NXCore) (with UCL Support)',

	/**
	 * Those below are private variables. DO NOT CHANGE THEM!
	 */
	initDone : false,
	storedHeaderWood : 0,
	storedHeaderClay : 0,
	storedHeaderIron : 0,
	configLoaded : false,
	standardColorPalette : new Array(),
	resourcesColorPalette : new Array(),
	resourcesAlertColorPalette : new Array(),
	standardColorPaletteFilled : false,
	resourcesColorPaletteFilled : false,
	resourcesAlertColorPaletteFilled : false,
	loyaltyData : new Array(),
	loyaltyDataLoaded : false,
	settings : {},
	settingsEmpty : false,
	sortedBy : '0,a',
	sortingInProgress : false,

	/* images (: */
	CUL : 'url(#ADDR#/pl_corner_up_left.gif)',
	CUR : 'url(#ADDR#/pl_corner_up_right.gif)',
	CDL : 'url(#ADDR#/pl_corner_down_left.gif)',
	CDR : 'url(#ADDR#/pl_corner_down_right.gif)',

	/* universalConsoleLogger section */
	scriptVerbosity : 10,
	useCallTracing : false,
	useInternalConsoleFirst : false,
	forceConsoleLoading : false,
	universalConsoleLoggerURL : '',
	log : function(msg, msgLvl) {if ((typeof msgLvl) == "undefined") { msgLvl = 1; }if (msgLvl <= this.scriptVerbosity) {if (this.useInternalConsoleFirst) {if ((typeof console) != "undefined") {if ((typeof console.log) != "undefined") {console.log(msg);return;}} else if (window.opera) {window.opera.postError(msg);return;}}if ((typeof unsafeWindow.universalConsoleLogger) == "undefined") {if (this.forceConsoleLoading) {if (this.universalConsoleLoggerURL == null) {return void(0);}if (this.consoleLoaderState == 0) {this.consoleLoader();this.consoleLoaderState = 1;}if (this.consoleLoaderState == 1) {this.delayedConsoleMessages.push(msg+'#delim#'+msgLvl);}if (this.consoleLoaderState == 2) {this.forceConsoleLoading = false;}}return;} else {if ((typeof unsafeWindow.universalConsoleLogger.log) == "undefined") {return;} else {if (this.consoleLoaderState == 1) {try {clearInterval(unsafeWindow.universalConsoleLoggerWait);this.delayedConsoleMessages.push(msg+'#delim#'+msgLvl);this.consoleLoaderState = 4;this.dumpDelayedMessages();} catch (e) {alert(e.description);}}unsafeWindow.universalConsoleLogger.log(msg, this.useCallTracing);}}}},
	consoleLoader : function () {try {var universalConsoleLoggerLoader = document.createElement('script');universalConsoleLoggerLoader.setAttribute('type','text/javascript');universalConsoleLoggerLoader.setAttribute('src',this.universalConsoleLoggerURL);universalConsoleLoggerLoader.setAttribute('id','universalConsoleLoggerScriptHolder');document.getElementsByTagName('head')[0].appendChild(universalConsoleLoggerLoader);universalConsoleLoggerLoader = void(0);unsafeWindow.universalConsoleLoggerWait=setInterval(" if ((typeof universalConsoleLogger)!='undefined') { try { clearInterval(unsafeWindow.universalConsoleLoggerWait); universalConsoleLogger.log('clearInterval succesful'); } catch (e) { universalConsoleLogger.log('still trying to clearInterval after loading console: '+e.description); } villagePreviewEnhancer.consoleLoaderState = 3; try { villagePreviewEnhancer.dumpDelayedMessages(); } catch (e) {} } else if (villagePreviewEnhancer.consoleLoaderState == 2) { clearInterval(unsafeWindow.universalConsoleLoggerWait); } ",500);} catch (e) {this.consoleLoaderState = 2;alert('universalConsoleLoader loading failed. (try())'+"\n"+e.description);}},
	dumpDelayedMessages : function () {try {this.log('init: '+this.delayedConsoleMessages.length+' messages pending');for (var i=0; i<this.delayedConsoleMessages.length; i++) {if (this.delayedConsoleMessages[i] != null) {this.log(this.delayedConsoleMessages[i].split('#delim#')[0], this.delayedConsoleMessages[i].split('#delim#')[1]);this.delayedConsoleMessages[i] = null;} else {this.log(i+': dumpDelayedMessages encountered `null` message');}}this.delayedConsoleMessages = new Array();this.consoleLoaderState = 3;} catch (e) {this.log(e.description);}return void(0);},
	delayedConsoleMessages : new Array(),
	consoleLoaderState : 0, // 0 - never launched, 1 - running, 2 - finished (console NOT loaded), 3 - finished (console loaded)
	/* endof universalConsoleLogger section */

	init : function () {
		if (!this.initDone) {
			try {
				this.log('VPE::init()', 1);
				if ((typeof document.body.tagName) != "undefined") {
					this.log('VPE::init() => Object.tagName is supported', 2);
				} else {
					this.log('VPE::init() => Object.tagName is NOT supported', 2);
				}
				this.log('VPE::init() => url: '+this.getURL(), 2);
				this.log('VPE::init() => image resources are located under: '+this.imageResourcesAddress, 2);
				this.log('VPE::debug => '+(document.getElementsByTagName('table').length), 1);
				this.isPA();
				this.CUL = this.CUL.replace(/#ADDR#/,this.imageResourcesAddress);
				this.CDL = this.CDL.replace(/#ADDR#/,this.imageResourcesAddress);
				this.CUR = this.CUR.replace(/#ADDR#/,this.imageResourcesAddress);
				this.CDR = this.CDR.replace(/#ADDR#/,this.imageResourcesAddress);
				this.loadHeader();
				this.loadDynamicMenuLink();
				this.initDone = true;

				if (this.getOverviewMode() == 'prod') {
					this.log('VPE::init() => load production via overview mode', 1);
					this.loadProduction(true);
				} else if (document.location.href.match(/screen=overview_villages(?:&|$)/) && !this.getOverviewMode()) {
					this.log('VPE::init() => load production without PA', 1);
					this.loadProduction(false);
				}

				if (document.location.href.match(/screen=settings(?:&|$)/)) {
					this.log('VPE::init() => screen is settings', 2);
					var tables = document.getElementsByTagName('table');
					for (var i=0; i<tables.length; i++) {
						if (tables[i].className == 'vis' && tables[i].innerHTML.match(/ticket\.php/)) {
							settingsMenu = tables[i];
						}
					}
					if (settingsMenu == null) {
						this.log('VPE::init() => Could not find table with settings menu despite settings screen');
					} else {
						var settingsCell = settingsMenu.insertRow(-1).insertCell(0);
						var settingsLink = document.createElement('a');
						settingsLink.id = 'submode=villagePreviewEnhacerSettings';
						settingsLink.href = '/game.php?screen=settings&mode=settings&submode=villagePreviewEnhacerSettings';
						//settingsLink.onclick = this.displaySettingsPanel;
						settingsLink.innerHTML = 'Village Preview Enhancer';
						settingsCell.appendChild(settingsLink);
						if (document.location.href.match(/submode=villagePreviewEnhacerSettings/)) {
							//var PA = document.forms.length > 1 ? true : false;
							this.log('VPE::init() => villagePreviewEnhacerSettings :: parentNode is: '+document.forms[0].parentNode.tagName, 2);
							this.log('VPE::init() => villagePreviewEnhacerSettings :: settingsMenu.rows.length is: '+settingsMenu.rows.length, 2);
							for (var i=0; i<settingsMenu.rows.length; i++) {
								if (!settingsMenu.rows[i].cells[0].innerHTML.match(settingsLink.id)) {
									settingsMenu.rows[i].cells[0].className = '';
								} else {
									settingsMenu.rows[i].cells[0].className = 'selected';
								}
							}
							var settingsSpace = document.forms[0].parentNode;
							settingsSpace.innerHTML = '';
							this.loadSettings(settingsSpace, this.isPA());
						}
					}
				}
				if (document.location.href.match(/screen=overview(?:&|$)/)) {
					this.loyaltyScan();
				}
			} catch (e) {
				this.log('VPE::init() :: failed => '+e, 0);
			}
		}
	},



	// ---------------------------------------------------------------------------------------
	//
	// display modification functions
	//
	// ---------------------------------------------------------------------------------------

	loadSettings : function (container, PA) {
		if ((typeof container) == "undefined") {
			this.log('VPE::loadSettings() => no Object to attach!', 0);
			return;
		}
		try {

			//container.style.border = '1px red solid';
			container.style.width = '85%';
			var settingsForm = ' \
				<small class="grey" style="float: right">ver: '+this.versionString+'</small> \
				<h3>Ustawienia skryptu: <em>Village Preview Enhancer</em></h3> \
				<form name="villagePreviewEnhancerSettings" onsubmit="return villagePreviewEnhancer.storeSettings()" action="/game.php?screen=settings&amp;mode=settings&amp;submode=villagePreviewEnhacerSettings"> \
					<table class="vis" width="100%"> \
						<tr><th colspan="2">Ustawienia nagłówka</th></tr> \
						<tr> \
							<td><label for="displayHeaderPercentResources">Procentowe wyświetlanie surowców:</td> \
							<td><input type="checkbox" id="displayHeaderPercentResources" name="displayHeaderPercentResources" value="true" '+(this.configGet('displayHeaderPercentResources') ? 'checked="checked" ' : '')+'/> \
						</tr> \
						<tr> \
							<td><label for="displayHeaderPercentWorkers">Procentowe wyświetlanie zajętości zagrody:</label></td> \
							<td><input type="checkbox" id="displayHeaderPercentWorkers" name="displayHeaderPercentWorkers" value="true" '+(this.configGet('displayHeaderPercentWorkers') ? 'checked="checked" ' : '')+'/> \
						</tr> \
						<tr> \
							<td><label for="displayHeaderSnobInfo">Wyświetlanie informacji o szlachcie:</label></td> \
							<td><input type="checkbox" id="displayHeaderSnobInfo" name="displayHeaderSnobInfo" value="true" '+(this.configGet('displayHeaderSnobInfo') ? 'checked="checked" ' : '')+'/></td> \
						</tr> \
						<tr><td colspan="2" style="background-color: transparent">&nbsp;</td></tr> \
						<tr><th colspan="2">Ustawienia przeglądu produkcji</th></tr> \
						<tr> \
							<td><label for="displayPreviewLoyalty" style="cursor: help;" title="Informacje o poparciu są szacunkowe i mogą nie mieć odzwierciedlenia w rzeczywistości. Informacja o poparciu w danej wiosce jest uzyskiwana dopiero w momencie wejścia w przegląd wioski">Informacja o poparciu*:</label></td> \
							<td><input type="checkbox" id="displayPreviewLoyalty" name="displayPreviewLoyalty" value="true" '+(this.configGet('displayPreviewLoyalty') ? 'checked="checked" ' : '')+'/></td> \
						</tr> \
						<tr> \
							<td><label for="displayPreviewPercentResources">Procentowe wyświetlanie surowców:</label></td> \
							<td><input type="checkbox" id="displayPreviewPercentResources" name="displayPreviewPercentResources" value="true" '+(this.configGet('displayPreviewPercentResources') ? 'checked="checked" ' : '')+'/></td> \
						</tr> \
						<tr> \
							<td><label for="displayPreviewPercentWorkers">Procentowe wyświetlanie zajętości zagrody:</label></td> \
							<td><input type="checkbox" id="displayPreviewPercentWorkers" name="displayPreviewPercentWorkers" value="true" '+(this.configGet('displayPreviewPercentWorkers') ? 'checked="checked" ' : '')+'/></td> \
						</tr> \
						<tr> \
							<td><label for="displayPreviewSnobInfo">Wyświetlanie informacji o szlachcie:</label></td> \
							<td><input type="checkbox" id="displayPreviewSnobInfo" name="displayPreviewSnobInfo" value="true" '+(this.configGet('displayPreviewSnobInfo') ? 'checked="checked" ' : '')+'/></td> \
						</tr> \
						<tr> \
							<td><label for="displayPreviewHighlightCurrentVillage">Podświetlaj aktualną wioskę:</label></td> \
							<td><input type="checkbox" id="displayPreviewHighlightCurrentVillage" name="displayPreviewHighlightCurrentVillage" value="true" '+(this.configGet('displayPreviewHighlightCurrentVillage') ? 'checked="checked" ' : '')+'/></td> \
						</tr> \
						<tr><td colspan="2" style="background-color: transparent">&nbsp;</td></tr> \
						<tr><th colspan="2">Opcje dla konta premium</th></tr> \
						<tr> \
							<td><label for="displayPreviewQueueFinish" style="cursor: help;" title="Wymuszenie wyświetlania kolejki budowy w jednej linii może NIE DZIAŁAĆ w każdej przeglądarce. Ustawienie wymuszania może doprowadzić do trudności w odczytaniu informacji."'+(!PA ? ' class="grey"' : '')+'>Format wyświetlania kolejki budowy*:</label></td> \
							<td> \
								<select size="1" id="displayPreviewQueueFinish" name="displayPreviewQueueFinish"'+(!PA ? ' disabled="disabled"' : '')+'> \
									<option value="standard" '+(this.configGet('displayPreviewQueueFinish') == 'standard' || !PA ? 'selected="selected"' : '')+'>standardowy</option> \
									<option value="try_inline" '+(this.configGet('displayPreviewQueueFinish') == 'try_inline' && PA ? 'selected="selected"' : '')+'>spróbuj w jednej linii</option> \
									<option value="force_inline" '+(this.configGet('displayPreviewQueueFinish') == 'force_inline' && PA ? 'selected="selected"' : '')+'>wymuś w jednej linii</option> \
									<option value="none" '+(this.configGet('displayPreviewQueueFinish') == 'none' && PA ? 'selected="selected"' : '')+'>ukryj informację o czasie zakończenia</option> \
								</select> \
							</td> \
						</tr> \
						<tr> \
							<td><label for="displayPreviewQueueVisibility"'+(!PA ? ' class="grey"' : '')+'>Widoczność kolumny z kolejką budowy:</label></td> \
							<td> \
								<select size="1" id="displayPreviewQueueVisibility" name="displayPreviewQueueVisibility"'+(!PA ? ' disabled="disabled"' : '')+'> \
									<option value="visible" '+(this.configGet('displayPreviewQueueVisibility') == 'visible' || !PA ? 'selected="selected"' : '')+'>zawsze widoczna</option> \
									<option value="auto" '+(this.configGet('displayPreviewQueueVisibility') == 'auto' && PA ? 'selected="selected"' : '')+'>ukryj gdy pusta</option> \
									<option value="hide" '+(this.configGet('displayPreviewQueueVisibility') == 'hide' && PA ? 'selected="selected"' : '')+'>zawsze ukrywaj</option> \
								</select> \
							</td> \
						</tr> \
						<tr> \
							<td><label for="displayPreviewTechVisibility"'+(!PA ? ' class="grey"' : '')+'>Widoczność kolumny z badaniami:</label></td> \
							<td> \
								<select size="1" id="displayPreviewTechVisibility" name="displayPreviewTechVisibility"'+(!PA ? ' disabled="disabled"' : '')+'> \
									<option value="visible" '+(this.configGet('displayPreviewTechVisibility') == 'visible' || !PA ? 'selected="selected"' : '')+'>zawsze widoczna</option> \
									<option value="auto" '+(this.configGet('displayPreviewTechVisibility') == 'auto' && PA ? 'selected="selected"' : '')+'>ukryj gdy pusta</option> \
									<option value="hide" '+(this.configGet('displayPreviewTechVisibility') == 'hide' && PA ? 'selected="selected"' : '')+'>zawsze ukrywaj</option> \
								</select> \
							</td> \
						</tr> \
						<tr> \
							<td><label for="displayPreviewRecruitVisibility"'+(!PA ? ' class="grey"' : '')+'>Widoczność kolumny z rekrutacją:</label></td> \
							<td> \
								<select size="1" id="displayPreviewRecruitVisibility" name="displayPreviewRecruitVisibility"'+(!PA ? ' disabled="disabled"' : '')+'> \
									<option value="visible" '+(this.configGet('displayPreviewRecruitVisibility') == 'visible' || !PA ? 'selected="selected"' : '')+'>zawsze widoczna</option> \
									<option value="auto" '+(this.configGet('displayPreviewRecruitVisibility') == 'auto' && PA ? 'selected="selected"' : '')+'>ukryj gdy pusta</option> \
									<option value="hide" '+(this.configGet('displayPreviewRecruitVisibility') == 'hide' && PA ? 'selected="selected"' : '')+'>zawsze ukrywaj</option> \
								</select> \
							</td> \
						</tr> \
						<tr><td colspan="2" style="background-color: transparent">&nbsp;</td></tr> \
						<tr><th colspan="2">Ustawienia dodatkowe</th></tr> \
						<tr> \
							<td><label for="useColorBlindPalette" style="cursor: help;" title="Użycie palety kolorów dla daltonistów zmienia przejście podświetlenia z `zielony &raquo; czerowny` na `żółty &raquo; niebieski`">Użyj palety kolorów dla daltonistów*:</label></td> \
							<td><input type="checkbox" id="useColorBlindPalette" name="useColorBlindPalette" value="true" '+(this.configGet('useColorBlindPalette') ? 'checked="checked" ' : '')+'/></td> \
						</tr> \
						<tr> \
							<td><label for="displayPreviewAllowSorting">Zezwól na sortowanie po wybranej kolumnie (wolne przy dużej ilości wiosek):</label></td> \
							<td><input type="checkbox" id="displayPreviewAllowSorting" name="displayPreviewAllowSorting" value="true" '+(this.configGet('displayPreviewAllowSorting') ? 'checked="checked" ' : '')+'/></td> \
						</tr> \
						<tr> \
							<td><label for="displayPreviewWorkersFlashOnOverfill" style="cursor: help;" title="Powoduje mruganie tła podświetlenia procentowego zagrody gdy w zagrodzie jest więcej ludności niż ta może pomieścić">Mrugaj gdy zagroda przepełniona*:</label></td> \
							<td> \
								<input type="checkbox" id="displayPreviewWorkersFlashOnOverfill" name="displayPreviewWorkersFlashOnOverfill" value="true" '+(this.configGet('displayPreviewWorkersFlashOnOverfill') ? 'checked="checked" ' : '')+'/> \
								<input type="text" id="displayPreviewWorkersFlashOnOverfillDelay" name="displayPreviewWorkersFlashOnOverfillDelay" size="2" maxlength="2" value="'+(this.configGet('displayPreviewWorkersFlashOnOverfillDelay'))+'" /><small><em>wartość w sekundach pomiędzy zmianami stanu</em></small> \
							</td> \
						</tr> \
						<tr><td colspan="2" style="background-color: transparent"></td></tr> \
						<tr> \
							<td><label for="displayPreviewResourcesAlert" style="cursor: help;" title="Zmienia podświetlenie danego surowca jeżeli jest poniżej podanej granicy procentowej. Podświetlenie zmienia się `zielony &raquo niebieski` im bliżej zerowej wartości surowca. Wartość procentowa powinna znajdować się w przedziale 5-90">Oznaczaj spadek surowców poniżej wartości procentowej*:</label></td> \
							<td> \
								<input type="checkbox" id="displayPreviewResourcesAlert" name="displayPreviewResourcesAlert" value="true" '+(this.configGet('displayPreviewResourcesAlert') ? 'checked="checked" ' : '')+'/> \
								<input type="text" id="displayPreviewResourcesAlertTreshold" name="displayPreviewResourcesAlertTreshold" size="2" maxlength="2" value="'+(this.configGet('displayPreviewResourcesAlertTreshold'))+'" /> \
							</td> \
						</tr> \
						<tr><td colspan="2"> \
							<input type="radio" id="displayPreviewResourcesAlertMarkTypeDynamic" name="displayPreviewResourcesAlertMarkType" value="dynamic" '+(this.configGet('displayPreviewResourcesAlertMarkTypeDynamic') ? 'checked="checked" ' : '')+'/> \
							<label for="displayPreviewResourcesAlertMarkTypeDynamic">Płynne przejście: niebieski (stan 0%) &raquo; zielony (stan granicy)</label> \
						</tr> \
						<tr><td colspan="2"> \
							<input type="radio" id="displayPreviewResourcesAlertMarkTypeColor" name="displayPreviewResourcesAlertMarkType" value="color" '+(this.configGet('displayPreviewResourcesAlertMarkTypeColor') ? 'checked="checked" ' : '')+'/> \
							<input type="text" id="displayPreviewResourcesAlertMarkValueColor" name="displayPreviewResourcesAlertMarkValueColor" size="6" maxlength="6" value="'+(this.configGet('displayPreviewResourcesAlertMarkValueColor'))+'" /> \
							<label for="displayPreviewResourcesAlertMarkTypeColor">Kolor w formacie hexadecymalnym (np. FFFFFF to biały)</label> \
						</td></tr> \
						<tr><td colspan="2" style="background-color: transparent"></td></tr> \
						<tr> \
							<td><label for="displayPreviewFullWorkersNeutralization" style="cursor: help;" title="Funkcja testowa!">Zmień podświetlenie maksymalnie rozbudowanej zagrody*:</label></td> \
							<td> \
								<input \
									type="checkbox" \
									id="displayPreviewFullWorkersNeutralization" \
									name="displayPreviewFullWorkersNeutralization" \
									value="true" \
									onchange="villagePreviewEnhancer.configFormWorkersNeutralizationActivator(this.checked);" \
									'+(this.configGet('displayPreviewFullWorkersNeutralization') ? 'checked="checked" ' : '')+' \
								/></td> \
						</tr> \
						<tr> \
							<td><label for="displayPreviewFullWorkersNeutralizationTreshold">Ilość wolnych miejsc poniżej której zmienić podświetlenie:</label></td> \
							<td><input type="text" id="displayPreviewFullWorkersNeutralizationTreshold" name="displayPreviewFullWorkersNeutralizationTreshold" size="5" maxlength="5" value="'+(this.configGet('displayPreviewFullWorkersNeutralizationTreshold'))+'" /></td> \
						</tr> \
						<tr><td colspan="2"> \
							<input type="radio" id="displayPreviewFullWorkersNeutralizationMarkTypePercent" name="displayPreviewFullWorkersNeutralizationMarkType" value="percent" '+(this.configGet('displayPreviewFullWorkersNeutralizationMarkTypePercent') ? 'checked="checked" ' : '')+'/> \
							<input type="text" id="displayPreviewFullWorkersNeutralizationMarkValuePercent" name="displayPreviewFullWorkersNeutralizationMarkValuePercent" size="6" maxlength="3" value="'+(this.configGet('displayPreviewFullWorkersNeutralizationMarkValuePercent'))+'" /> \
							<label for="displayPreviewFullWorkersNeutralizationMarkTypePercent">Kolor z palety kolorów z podświetlania zagrody (wartość procentowa koloru 0-100)</label> \
						</tr> \
						<tr><td colspan="2"> \
							<input type="radio" id="displayPreviewFullWorkersNeutralizationMarkTypeColor" name="displayPreviewFullWorkersNeutralizationMarkType" value="color" '+(this.configGet('displayPreviewFullWorkersNeutralizationMarkTypeColor') ? 'checked="checked" ' : '')+'/> \
							<input type="text" id="displayPreviewFullWorkersNeutralizationMarkValueColor" name="displayPreviewFullWorkersNeutralizationMarkValueColor" size="6" maxlength="6" value="'+(this.configGet('displayPreviewFullWorkersNeutralizationMarkValueColor'))+'" /> \
							<label for="displayPreviewFullWorkersNeutralizationMarkTypeColor">Kolor w formacie hexadecymalnym (np. FFFFFF to biały)</label> \
						</td></tr> \
						\
						<tr><td colspan="2" style="background-color: transparent"></td></tr> \
						<tr><td colspan="2"><input type="submit" value="Zapisz ustawienia" /></td></tr> \
						<tr><td colspan="2" style="background-color: transparent"</td></tr> \
						<tr><td colspan="2"><em>*) Opcje oznaczone gwiazdką posiadają podpowiedzi.</em></td></tr> \
						<tr> \
							<td><label for=""> </label></td> \
							<td> </td> \
						</tr> \
					</table> \
				</form> \
			';
			container.innerHTML = settingsForm;
			this.configFormWorkersNeutralizationActivator(this.configGet('displayPreviewFullWorkersNeutralization'));
			//return;


		} catch (e) {
			this.log(e, 0);
		}
	},

	loadDynamicMenuLink : function () {
		this.log('VPE::loadDynamicMenuLink()', 2);
		try {
			var tables = document.getElementsByTagName('table');
			for (var i=0; i<tables.length; i++) {
				if (tables[i].className == 'menu_column' && tables[i].rows[0].cells[0].innerHTML.match(/mode=profile/)) {
					// we have our table
					tables[i].insertRow(-1).insertCell(0).innerHTML = '<a href="/game.php?screen=settings&mode=settings&submode=villagePreviewEnhacerSettings">Village Preview Enhancer</a>';
					break;
				}
			}
		} catch (e) {
			this.log('VPE::loadDynamicMenuLink() => '+e), 0;
		}
	},

	loadHeader : function () {
		try {
			// do we have header?
			if ((document.getElementById('wood')) != null && (document.getElementById('stone')) != null && (document.getElementById('iron')) != null) {
				// yes we have (:
				this.log('VPE::loadHeader() => got header', 1);

				if (this.configGet('displayHeaderPercentResources')) {
					this.headerUpdater();
					unsafeWindow.setInterval('villagePreviewEnhancer.headerUpdater()', 500);
				}

				if (this.configGet('displayHeaderPercentWorkers')) {
					this.headerWorkers();
				}
				if (this.configGet('displayHeaderSnobInfo')) {
					this.headerSnob();
				}

			} else {
				this.log('VPE::loadHeader() => no header here :: bailing out', 1);
			}
		} catch (e) {
			this.log(e, 0);
		}
	},

	headerWoodUpdater : function () {
		try {
			var currentHeaderCapacity = parseInt(document.getElementById('storage').innerHTML);
			var currentHeaderWood = parseInt(document.getElementById('wood').innerHTML.match(/\d+/)[0]);
			if (currentHeaderWood != this.storedHeaderWood) {
				this.storedHeaderWood = currentHeaderWood;
				var woodP = Math.round((currentHeaderWood*100)/currentHeaderCapacity);
				if (document.getElementById('wood_percent') == null) {
					var woodPspan = document.createElement('small');
					woodPspan.id = 'wood_percent';
					woodPspan.className = 'grey';
					document.getElementById('wood').parentNode.appendChild(woodPspan);
				} else {
					var woodPspan = document.getElementById('wood_percent');
				}
				woodPspan.innerHTML = '('+woodP+'%)&nbsp;';
			}
		} catch (e) {
			this.log(e, 0);
		}
		return false;
	},
	headerClayUpdater : function () {
		try {
			var currentHeaderCapacity = parseInt(document.getElementById('storage').innerHTML);
			var currentHeaderClay = parseInt(document.getElementById('stone').innerHTML.match(/\d+/)[0]);
			if (currentHeaderClay != this.storedHeaderClay) {
				this.storedHeaderClay = currentHeaderClay;
				var clayP = Math.round((currentHeaderClay*100)/currentHeaderCapacity);
				if (document.getElementById('clay_percent') == null) {
					var clayPspan = document.createElement('small');
					clayPspan.id = 'clay_percent';
					clayPspan.className = 'grey';
					document.getElementById('stone').parentNode.appendChild(clayPspan);
				} else {
					var clayPspan = document.getElementById('clay_percent');
				}
				clayPspan.innerHTML = '('+clayP+'%)&nbsp;';
			}
		} catch (e) {
			this.log(e, 0);
		}
		return false;
	},
	headerIronUpdater : function () {
		try {
			var currentHeaderCapacity = parseInt(document.getElementById('storage').innerHTML);
			var currentHeaderIron = parseInt(document.getElementById('iron').innerHTML.match(/\d+/)[0]);
			if (currentHeaderIron != this.storedHeaderIron) {
				this.storedHeaderIron = currentHeaderIron;
				var ironP = Math.round((currentHeaderIron*100)/currentHeaderCapacity);
				if (document.getElementById('iron_percent') == null) {
					var ironPspan = document.createElement('small');
					ironPspan.id = 'iron_percent';
					ironPspan.className = 'grey';
					document.getElementById('iron').parentNode.appendChild(ironPspan);
				} else {
					var ironPspan = document.getElementById('iron_percent');
				}
				ironPspan.innerHTML = '('+ironP+'%)&nbsp;';
			}
		} catch (e) {
			this.log(e, 0);
		}
		return false;
	},
	headerWorkers : function () {
		try {
			var tables = document.getElementsByTagName('table');
			for (var i=0; i<tables.length; i++) {
				if (tables[i].className == 'navi-border' && tables[i].rows.length == 1 && tables[i].innerHTML.match(/face\.png/)) {
					workers = tables[i].rows[0].cells[0].getElementsByTagName('table')[0].rows[0].cells[1].innerHTML.match(/(\d+)\/(\d+)/);
					workersP = Math.round((parseInt(workers[1])*100)/parseInt(workers[2]));
					var workersPspan = document.createElement('small');
					workersPspan.className = 'grey';
					workersPspan.innerHTML = ' ('+workersP+'%)';
					tables[i].rows[0].cells[0].getElementsByTagName('table')[0].rows[0].cells[1].appendChild(workersPspan);
					break;
				}
			}
		} catch(e) {
			this.log(e, 0);
		}
	},
	headerSnob : function () {
		try {
			var headerBar = document.getElementById('storage').parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode;
			if (headerBar.cells[headerBar.cells.length-1].innerHTML.match(/att.png/i)) {
				var newCell = headerBar.insertCell(headerBar.cells.length-1);
			} else {
				var newCell = headerBar.insertCell(headerBar.cells.length);
			}
			var pack = this.calcPack(this.getWood(), this.getClay(), this.getIron());
			var workersLeft = (this.getWorkers().limit-this.getWorkers().current);
			workersLeft = workersLeft < 0 ? 0 : workersLeft;
			var snob = this.calcSnob(this.getWood(), this.getClay(), this.getIron(), workersLeft);
			if (this.getWorldSetting('snobType') == 'gold') {
				var snobTypeLang = 'monet do wybicia';
			} else if (this.getWorldSetting('snobType') == 'res') {
				var snobTypeLang = 'paczek surowców do złożenia';
			}
			var snob_data = '<td align="center"><img src="/graphic/'+this.getWorldSetting('snobType')+'.png" style="cursor:help;" title="Ilość możliwych '+snobTypeLang+': '+pack+'"></td><td align="center"><a href="/game.php?village='+this.getVillageId()+'&amp;screen=snob">&nbsp;'+pack+'&nbsp;</a></td><td align="center"><img src="/graphic/unit/unit_snob.png" style="cursor:help;" title="Ilość możliwych szlachciów do zrekrutowania: '+snob[0]+'"></td><td align="center"><a href="/game.php?village='+this.getVillageId()+'&amp;screen=snob">&nbsp;'+snob[0]+'</a><span class="grey" title="Ilość możliwych szlachciów do zrekrutowania z surowców: '+snob[1]+'" style="cursor: help"> / '+snob[1]+'</span></td>';
			newCell.innerHTML = '<table class="navi-border" style="border-collapse: collapse;"><tr><td><table class="box" cellspacing="0"><tr height="20">'+snob_data+'</tr></table></td></tr></table>';
		} catch (e) {
			this.log(e, 0);
		}
	},


	loadProduction : function (PA) {
		try {
			if (!PA) {
				this.log('VPE::loadProduction() => PA not enabled', 1);
				var vList;
				var tt = document.getElementsByTagName('table');
				//vList = tt[(tt.length-1)];
				//if (vList.rows.length == 1) {
					//vList = tt[(tt.length-2)];
				//}
				for (var i=0; i<tt.length; i++) {
					if (tt[i].rows.length > 1 && tt[i].rows[0].getElementsByTagName('th').length > 2 && tt[i].rows[1].cells[0].innerHTML.match(/village=[0-9]+/)) {
						vList = tt[i];
						break;
					}
				}
			} else {
				var vList = document.getElementById('overview').parentNode.getElementsByTagName('table');
				for (var i=0; i<vList.length; i++) {
					//if (vList[i].rows[0].getElementsByTagName('th').length > 1) {
					if (vList[i].rows.length > 1 && vList[i].rows[0].getElementsByTagName('th').length > 2 && vList[i].rows[1].cells[0].innerHTML.match(/village=[0-9]+/)) {
						vList = vList[i];
						break;
					}
				}
			}
			if ((typeof vList) == "undefined") {
				this.log('VPE::loadProduction() => something terrible happend while searching for village list', 0);
			}
			if (!vList.rows[1].cells[0].innerHTML.match(/village=/)) {
				this.log('VPE::loadProduction() => vList NOT found :: False alarm', 2);
				return false;
			} else {
				this.log('VPE::loadProduction() => vList found ('+vList.rows.length+')', 2);
			}
			vList.id = 'village_list';
			if (this.configGet('displayPreviewPercentResources') || this.configGet('displayPreviewPercentWorkers')) {
				// let's do the color table before entering any loops... should save some time (:
				this.fillStandardColorTable();
				this.fillResourcesColorTable();
				if (this.configGet('displayPreviewResourcesAlert')) {
					var treshold = parseInt(this.configGet('displayPreviewResourcesAlertTreshold'));
					this.log('VPE::loadProduction() => Resources alert requested :: treshold is: ('+(typeof treshold)+') `'+treshold+'`', 1);
					if (isNaN(treshold) || treshold < 5 || treshold > 90) {
						treshold = 0;
					} else {
						if ((this.configGet('displayPreviewResourcesAlertMarkTypeDynamic')) || (!this.configGet('displayPreviewResourcesAlertMarkTypeDynamic') && !this.configGet('displayPreviewResourcesAlertMarkTypeColor'))) {
							this.log('VPE::loadProduction() => calling VPE::fillAlertColorTable()', 1);
							this.fillResourcesAlertColorTable();
						}
					}
				} else {
					var treshold = 0;
				}
			}
			vList.style.width = '100%';
			vList.deleteRow(0);
			//vList.insertBefore(vList.rows[0], vList.rows[3]);
			var sumWood = 0;
			var sumClay = 0;
			var sumIron = 0;
			var sumStorage = 0;
			var sumWorkers = new Array(0,0);
			var sumPacks = 0;
			var sumSnobs = new Array(0,0);
			var sumVillages = 0;
			var sumPoints = 0;
			var colQueueEmpty = true;
			var colTechEmpty = true;
			var colRecruitEmpty = true;


			for (var i=0; i<vList.rows.length; i++) {
				vList.rows[i].id = i;
				var row = vList.rows[i];
				//row.cells[0].abbr =
				try {
					row.cells[0].abbr = row.cells[0].innerHTML.htmlentities().match(/.*([0-9]{3}[|][0-9]{3}).*?$/m)[1];
					this.log('VBE::loadProduction() => coords: '+row.cells[0].abbr, 1);
				} catch (e) {
					this.log('VPE::loadProduction() => '+e, 0);
				}
				var storage = parseInt(row.cells[3].innerHTML);
				sumVillages++;
				row.cells[1].abbr = row.cells[1].innerHTML.replace(/<.*>/g,'').replace(/[.]/g,'');
				sumPoints += parseInt(row.cells[1].innerHTML.replace(/<.*>/,''));
				var villageId = parseInt(row.cells[0].innerHTML.match(/village=(\d+)/i)[1]);
				row.cells[1].style.textAlign = 'right';
				if (this.configGet('displayPreviewLoyalty')) {
					var loyalty = row.insertCell(2);
					loyalty.style.textAlign = 'right';
					var storedLoyalty = this.getLoyalty(villageId);
					if (storedLoyalty != null) {
						storedLoyalty = storedLoyalty.split(',');
						var vLoyaltyT = storedLoyalty[0];
						var vLoyaltyL = storedLoyalty[1];
					} else {
						var vLoyaltyT = null;
						var vLoyaltyL = null;
					}
					if (vLoyaltyT == null || vLoyaltyL == null) {
						loyalty.innerHTML = '<small class="grey" style="cursor:help" title="Wejdź do przeglądu wioski aby uzyskać aktualne informacje o poparciu">???</small>';
					} else {
						var now = parseInt(parseInt(parseInt(new Date().getTime()/1000)/60)/60);
						var diff = (now - vLoyaltyT)*this.getWorldSetting('loyaltyPerHour');
						vLoyaltyL = (parseInt(vLoyaltyL)+diff) > 99 ? 100 : (parseInt(vLoyaltyL)+diff);
						loyalty.innerHTML = '<small class="grey" style="cursor:help" title="Ostatnie sprawdzanie: '+diff+' godzin temu">'+vLoyaltyL+'</small>';
					}

				}
				var oldResourcesIndex = this.configGet('displayPreviewLoyalty') ? 3 : 2;
				woodCol = row.insertCell(oldResourcesIndex+1);
				clayCol = row.insertCell(oldResourcesIndex+2);
				ironCol = row.insertCell(oldResourcesIndex+3);
				woodCol.style.textAlign = clayCol.style.textAlign = ironCol.style.textAlign = 'right';
				woodCol.innerHTML = row.cells[oldResourcesIndex].innerHTML.match(/holz\.png.*?>(.*?)<img/i)[1];
				var rWood = parseInt(woodCol.innerHTML.replace(/<.*?>/gi,'').replace('.',''));
				woodCol.abbr = rWood;
				woodCol.id = 'wood_'+villageId;
				sumWood += rWood;

				clayCol.innerHTML = row.cells[oldResourcesIndex].innerHTML.match(/lehm\.png.*?>(.*?)<img/i)[1];
				var rClay = parseInt(clayCol.innerHTML.replace(/<.*?>/gi,'').replace('.',''));
				clayCol.abbr = rClay;
				clayCol.id = 'clay_'+villageId;
				sumClay += rClay;

				ironCol.innerHTML = row.cells[oldResourcesIndex].innerHTML.match(/eisen\.png.*?>(.*?)$/i)[1];
				var rIron = parseInt(ironCol.innerHTML.replace(/<.*?>/gi,'').replace('.',''));
				ironCol.abbr = rIron;
				sumIron += rIron;

				if (this.configGet('displayPreviewPercentResources')) {
					woodPCol = row.insertCell(oldResourcesIndex+1);
					clayPCol = row.insertCell(oldResourcesIndex+3);
					ironPCol = row.insertCell(oldResourcesIndex+5);
					var woodP = Math.round((parseInt(woodCol.innerHTML.replace(/<.*?>/gi,'').replace('.',''))*100)/storage);
					woodPCol.innerHTML = '<small>'+woodP+'%</small>';
					woodPCol.id = 'woodP_'+villageId;
					if (woodP < treshold) {
						if ((this.configGet('displayPreviewResourcesAlertMarkTypeDynamic')) || (!this.configGet('displayPreviewResourcesAlertMarkTypeDynamic') && !this.configGet('displayPreviewResourcesAlertMarkTypeColor'))) {
							this.log('VPE::loadProduction() => '+villageId+'::Wood is using resourcesAlertColorPalette with index: '+(treshold-woodP)+' :: value is: `'+this.resourcesAlertColorPalette[(treshold-woodP)]+'`', 2);
							woodPCol.style.backgroundColor = this.resourcesAlertColorPalette[(treshold-woodP)];
						} else if (this.configGet('displayPreviewResourcesAlertMarkTypeColor')) {
							woodPCol.style.backgroundColor = '#'+this.configGet('displayPreviewResourcesAlertMarkValueColor');
						}
					} else {
						woodPCol.style.backgroundColor = this.resourcesColorPalette[woodP-treshold];
					}
					woodPCol.style.color = '#FFFFFF';

					var clayP = Math.round((parseInt(clayCol.innerHTML.replace(/<.*?>/gi,'').replace('.',''))*100)/storage);
					clayPCol.innerHTML = '<small>'+clayP+'%</small>';
					if (clayP < treshold) {
						if ((this.configGet('displayPreviewResourcesAlertMarkTypeDynamic')) || (!this.configGet('displayPreviewResourcesAlertMarkTypeDynamic') && !this.configGet('displayPreviewResourcesAlertMarkTypeColor'))) {
							this.log('VPE::loadProduction() => '+villageId+'::Clay is using resourcesAlertColorPalette with index: '+(treshold-clayP)+' :: value is: `'+this.resourcesAlertColorPalette[(treshold-clayP)]+'`', 2);
							clayPCol.style.backgroundColor = this.resourcesAlertColorPalette[(treshold-clayP)];
						} else if (this.configGet('displayPreviewResourcesAlertMarkTypeColor')) {
							clayPCol.style.backgroundColor = '#'+this.configGet('displayPreviewResourcesAlertMarkValueColor');
						}
					} else {
						clayPCol.style.backgroundColor = this.resourcesColorPalette[(clayP-treshold)];
					}
					clayPCol.style.color = '#FFFFFF';

					var ironP = Math.round((parseInt(ironCol.innerHTML.replace(/<.*?>/gi,'').replace('.',''))*100)/storage);
					ironPCol.innerHTML = '<small>'+ironP+'%</small>';
					if (ironP < treshold) {
						if ((this.configGet('displayPreviewResourcesAlertMarkTypeDynamic')) || (!this.configGet('displayPreviewResourcesAlertMarkTypeDynamic') && !this.configGet('displayPreviewResourcesAlertMarkTypeColor'))) {
							this.log('VPE::loadProduction() => '+villageId+'::Iron is using resourcesAlertColorPalette with index: '+(treshold-ironP)+' :: value is: `'+this.resourcesAlertColorPalette[(treshold-ironP)]+'`', 2);
							ironPCol.style.backgroundColor = this.resourcesAlertColorPalette[(treshold-ironP)];
						} else if (this.configGet('displayPreviewResourcesAlertMarkTypeColor')) {
							ironPCol.style.backgroundColor = '#'+this.configGet('displayPreviewResourcesAlertMarkValueColor');
						}
					} else {
						ironPCol.style.backgroundColor = this.resourcesColorPalette[ironP-treshold];
					}
					ironPCol.style.color = '#FFFFFF';
					woodPCol.style.textAlign = clayPCol.style.textAlign = ironPCol.style.textAlign = 'right';
				} else {
					woodCol.colSpan = '2';
					clayCol.colSpan = '2';
					ironCol.colSpan = '2';
				}

				var storageIndex = 6;
				if (this.configGet('displayPreviewLoyalty')) {
					storageIndex += 1;
				}
				if (this.configGet('displayPreviewPercentResources')) {
					storageIndex += 3;
				}
				row.cells[storageIndex].colSpan = '2';
				row.cells[storageIndex].style.textAlign = 'right';
				sumStorage += parseInt(row.cells[storageIndex].innerHTML);

				var oldWorkersIndex = 7;
				if (this.configGet('displayPreviewLoyalty')) {
					oldWorkersIndex += 1;
				}
				if (this.configGet('displayPreviewPercentResources')) {
					oldWorkersIndex += 3;
				}
				var workers = row.cells[oldWorkersIndex].innerHTML.match(/(\d+)\/(\d+)/);
				sumWorkers[0] += parseInt(workers[1]);
				sumWorkers[1] += parseInt(workers[2]);
				row.cells[oldWorkersIndex].style.textAlign = 'right';
				row.cells[oldWorkersIndex].innerHTML = workers[1]+'&nbsp;<span class="grey">/</span>&nbsp;'+workers[2];
				row.cells[oldWorkersIndex].style.padding = '0px 5px';
				if (this.configGet('displayPreviewPercentWorkers')) {
					var workersP = Math.round((workers[1]*100)/workers[2]);
					if (workersP > 100) {
						var overfill = true;
					} else {
						var overfill = false;
					}
					workersP = workersP > 100 ? 100 : workersP;
					var workersPCol = row.insertCell(oldWorkersIndex);
					workersPCol.innerHTML = '<small>'+workersP+'%</small>';

					if (!overfill) {
						if (this.configGet('displayPreviewFullWorkersNeutralization') && workers[2] >= 24000) {
							this.log('VPE::loadProduction() => workers hightlight neutralization ('+villageId+')', 2);
							if (this.configGet('displayPreviewFullWorkersNeutralizationTreshold') > (workers[2]-workers[1])) {
								this.log('VPE::loadProduction() => workers highlight neutralization ('+villageId+') => neutralization required', 2);

								if (this.configGet('displayPreviewFullWorkersNeutralizationMarkTypePercent')) {
									this.log('VPE::loadProduction() => workers highlight neutralization ('+villageId+') => neutralizatiing with standardColorPalette('+this.configGet('displayPreviewFullWorkersNeutralizationMarkValuePercent')+')', 2);
									workersPCol.style.backgroundColor = this.standardColorPalette[this.configGet('displayPreviewFullWorkersNeutralizationMarkValuePercent')];
								} else if (this.configGet('displayPreviewFullWorkersNeutralizationMarkTypeColor')) {
									this.log('VPE::loadProduction() => workers highlight neutralization ('+villageId+') => neutralizatiing with user color #'+this.configGet('displayPreviewFullWorkersNeutralizationMarkValueColor')+'', 2);
									workersPCol.style.backgroundColor = '#'+this.configGet('displayPreviewFullWorkersNeutralizationMarkValueColor');
								} else {
									workersPCol.style.backgroundColor = this.standardColorPalette[workersP];
								}
							} else {
								workersPCol.style.backgroundColor = this.standardColorPalette[workersP];
								this.log('VPE::loadProduction() => workers neutralization not required for: '+villageId, 2);
							}
						} else {
							workersPCol.style.backgroundColor = this.standardColorPalette[workersP];
						}
					} else {
						if (this.configGet('displayPreviewWorkersFlashOnOverfill')) {
							workersPCol.id = 'workers_'+villageId;
							unsafeWindow.setInterval('villagePreviewEnhancer.flashWorkersOverfill("'+workersPCol.id+'")', this.configGet('displayPreviewWorkersFlashOnOverfillDelay')*1000);
							workersPCol.style.backgroundColor = this.standardColorPalette[100];
						} else {
							workersPCol.style.backgroundColor = this.standardColorPalette[100];
						}

					}
					workersPCol.style.textAlign = 'right';
					workersPCol.style.color = '#FFFFFF';
				} else {
					row.cells[oldWorkersIndex].colSpan = '2';
				}

				if (PA) {
					if (this.configGet('displayPreviewQueueVisibility') != 'none') {
						try {
							var buildQueueFinishTime = row.cells[(row.cells.length-3)].innerHTML.replace(/\r|\n|\t/g,'').replace(/(.*)<br(..)?>(.*)/i,'$3').match(/.*title=".*? - (.*?)".*?$/)[1].htmlentities(); // "
							buildQueueFinishTime = this.parseFinishTime(buildQueueFinishTime);
						} catch (e) {
							var buildQueueFinishTime = 0;
						}
						row.cells[(row.cells.length-3)].abbr = buildQueueFinishTime;
						if (this.configGet('displayPreviewQueueFinish') != 'standard') {
							var queue = row.cells[(row.cells.length-3)].innerHTML.replace(/\r|\n|\t/g,'');
							if (queue.match(/[<br(..)?>]/im)) {
								switch (this.configGet('displayPreviewQueueFinish')) {
									case 'try_inline':
										row.cells[(row.cells.length-3)].innerHTML = queue.replace(/(.*)<br(..)?>(.*)/i,'<span style="float: right; clear: left;">$1</span> <span style="float: left;">$3</span>');
										break;
									case 'force_inline':
										row.cells[(row.cells.length-3)].innerHTML = queue.replace(/(.*)<br(..)?>(.*)/i,'<span style="float: left;">$3</span>$1');
										row.cells[(row.cells.length-3)].style.textAlign='right';
										row.cells[(row.cells.length-3)].style.whiteSpace='nowrap';
										row.cells[(row.cells.length-3)].style.width='auto';
										break;
									case 'none':
										row.cells[(row.cells.length-3)].innerHTML = queue.replace(/.*?<br(..)?>/i,'');
										break;
									default:
										this.log('VPE::loadProduction() => queue config error!', 0);
								}
							}
						}
					}
					if (row.cells[(row.cells.length-3)].innerHTML.length > 0) {
						colQueueEmpty = false;
					}
					if (row.cells[(row.cells.length-2)].innerHTML.length > 0) {
						colTechEmpty = false;
					}
					if (row.cells[(row.cells.length-1)].innerHTML.length > 0) {
						colRecruitEmpty = false;
					}
				}
				if (this.configGet('displayPreviewSnobInfo')) {
					var snobInfoIndex = PA ? row.cells.length-3 : row.cells.length;
					var packCol = row.insertCell(snobInfoIndex);
					var pack = this.calcPack(rWood, rClay, rIron);
					packCol.innerHTML = '<a href="/game.php?village='+villageId+'&amp;screen=snob">'+pack+'</a>';
					packCol.style.cursor = 'help';
					if (this.getWorldSetting('snobType') == 'gold') {
						var snobTypeLang = 'monet do wybicia';
					} else if (this.getWorldSetting('snobType') == 'res') {
						var snobTypeLang = 'paczek surowców do złożenia';
					}
					packCol.title = 'Ilość możliwych '+snobTypeLang+': '+pack;
					packCol.style.textAlign = 'right';
					packCol.style.padding = '0px 5px';
					sumPacks += pack;
					var snobCol = row.insertCell(snobInfoIndex+1);
					var workersLeft = (workers[2]-workers[1]) < 0 ? 0 : workers[2]-workers[1];
					var snob = this.calcSnob(rWood, rClay, rIron, workersLeft);
					snobCol.innerHTML = '<a href="/game.php?village='+villageId+'&amp;screen=snob">'+snob[0]+'</a> / <span class="grey" title="Ilość szlachciców do zrekrutowania z surowców: '+snob[1]+'">'+snob[1]+'</span>';
					snobCol.style.cursor = 'help';
					snobCol.title = 'Ilość szlachciców do zrekrutowania: '+snob[0];
					snobCol.style.textAlign = 'right';
					snobCol.style.padding = '0px 5px';
					sumSnobs[0] += snob[0];
					sumSnobs[1] += snob[1];

				}
				row.cells[oldResourcesIndex].style.display='none';
				if (this.configGet('displayPreviewHighlightCurrentVillage') && villageId == this.getVillageId()) {
					row.cells[0].style.backgroundColor = '#F0D49A';
					//row.cells[0].className = 'selected';
				}
			}

			// header (:
			var header = vList.insertRow(0);
			header.style.height = '25px';
			var vName = document.createElement('th');
			if (this.configGet('displayPreviewAllowSorting')) {
				vName.innerHTML = '<a onclick="villagePreviewEnhancer.sortProduction(this)" style="cursor: s-resize">Wioska</a>';
			} else {
				vName.innerHTML = 'Wioska';
			}
			vName.style.backgroundImage = this.CUL;
			vName.style.backgroundPosition = 'left top';
			vName.style.backgroundRepeat = 'no-repeat';
			header.appendChild(vName);
			var vPts = document.createElement('th');
			if (this.configGet('displayPreviewAllowSorting')) {
				vPts.innerHTML = '<a onclick="villagePreviewEnhancer.sortProduction(this, true)" style="cursor: s-resize">P.</a>';
			} else {
				vPts.innerHTML = 'P.';
			}
			header.appendChild(vPts);
			if (this.configGet('displayPreviewLoyalty')) {
				var vLoyalty = document.createElement('th');
				if (this.configGet('displayPreviewAllowSorting')) {
					vLoyalty.innerHTML = '<a onclick="villagePreviewEnhancer.sortProduction(this)" style="cursor: s-resize"><img src="/graphic/ally_rights/lead.png" /></a>';
				} else {
					vLoyalty.innerHTML = '<img src="/graphic/ally_rights/lead.png" />';
				}
				vLoyalty.style.backgroundImage = this.CUR;
				vLoyalty.style.backgroundPosition = 'right top';
				vLoyalty.style.backgroundRepeat = 'no-repeat';
				header.appendChild(vLoyalty);
			} else {
				vPts.style.backgroundImage = this.CUR;
				vPts.style.backgroundPosition = 'right top';
				vPts.style.backgroundRepeat = 'no-repeat';
			}
			var vWoodP = document.createElement('th');
			if (this.configGet('displayPreviewAllowSorting')) {
				vWoodP.innerHTML = '<a onclick="villagePreviewEnhancer.sortProduction(this)" style="cursor: s-resize"><img src="/graphic/holz.png" /></a>';
			} else {
				vWoodP.innerHTML = '<img src="/graphic/holz.png" />';
			}
			vWoodP.style.backgroundImage = this.CUL;
			vWoodP.style.backgroundPosition = 'left top';
			vWoodP.style.backgroundRepeat = 'no-repeat';
			header.appendChild(vWoodP);
			var vWood = document.createElement('th');
			if (this.configGet('displayPreviewAllowSorting')) {
				vWood.innerHTML = '<a onclick="villagePreviewEnhancer.sortProduction(this, true)" style="cursor: s-resize">Drewno</a>';
			} else {
				vWood.innerHTML = 'Drewno';
			}
			vWood.style.backgroundImage = this.CUR;
			vWood.style.backgroundPosition = 'right top';
			vWood.style.backgroundRepeat = 'no-repeat';
			header.appendChild(vWood);

			var vClayP = document.createElement('th');
			if (this.configGet('displayPreviewAllowSorting')) {
				vClayP.innerHTML = '<a onclick="villagePreviewEnhancer.sortProduction(this)" style="cursor: s-resize"><img src="/graphic/lehm.png" /></a>';
			} else {
				vClayP.innerHTML = '<img src="/graphic/lehm.png" />';
			}
			vClayP.style.backgroundImage = this.CUL;
			vClayP.style.backgroundPosition = 'left top';
			vClayP.style.backgroundRepeat = 'no-repeat';
			header.appendChild(vClayP);
			var vClay = document.createElement('th');
			if (this.configGet('displayPreviewAllowSorting')) {
				vClay.innerHTML = '<a onclick="villagePreviewEnhancer.sortProduction(this, true)" style="cursor: s-resize">Glina</a>';
			} else {
				vClay.innerHTML = 'Glina';
			}
			vClay.style.backgroundImage = this.CUR;
			vClay.style.backgroundPosition = 'right top';
			vClay.style.backgroundRepeat = 'no-repeat';
			header.appendChild(vClay);

			var vIronP = document.createElement('th');
			if (this.configGet('displayPreviewAllowSorting')) {
				vIronP.innerHTML = '<a onclick="villagePreviewEnhancer.sortProduction(this)" style="cursor: s-resize"><img src="/graphic/eisen.png" /></a>';
			} else {
				vIronP.innerHTML = '<img src="/graphic/eisen.png" />';
			}
			vIronP.style.backgroundImage = this.CUL;
			vIronP.style.backgroundPosition = 'left top';
			vIronP.style.backgroundRepeat = 'no-repeat';
			header.appendChild(vIronP);
			var vIron = document.createElement('th');
			if (this.configGet('displayPreviewAllowSorting')) {
				vIron.innerHTML = '<a onclick="villagePreviewEnhancer.sortProduction(this, true)" style="cursor: s-resize">Żelazo</a>';
			} else {
				vIron.innerHTML = 'Żelazo';
			}
			vIron.style.backgroundImage = this.CUR;
			vIron.style.backgroundPosition = 'right top';
			vIron.style.backgroundRepeat = 'no-repeat';
			header.appendChild(vIron);

			var vStorageP = document.createElement('th');
			if (this.configGet('displayPreviewAllowSorting')) {
				vStorageP.innerHTML = '<a onclick="villagePreviewEnhancer.sortProduction(this)" style="cursor: s-resize"><img src="/graphic/res.png" /></a>';
			} else {
				vStorageP.innerHTML = '<img src="/graphic/res.png" />';
			}
			vStorageP.style.backgroundImage = this.CUL;
			vStorageP.style.backgroundPosition = 'left top';
			vStorageP.style.backgroundRepeat = 'no-repeat';
			header.appendChild(vStorageP);
			var vStorage = document.createElement('th');
			if (this.configGet('displayPreviewAllowSorting')) {
				vStorage.innerHTML = '<a onclick="villagePreviewEnhancer.sortProduction(this)" style="cursor: s-resize">Max.</a>';
			} else {
				vStorage.innerHTML = 'Max.';
			}
			vStorage.style.backgroundImage = this.CUR;
			vStorage.style.backgroundPosition = 'right top';
			vStorage.style.backgroundRepeat = 'no-repeat';
			header.appendChild(vStorage);

			var vWorkersP = document.createElement('th');
			if (this.configGet('displayPreviewAllowSorting')) {
				vWorkersP.innerHTML = '<a onclick="villagePreviewEnhancer.sortProduction(this)" style="cursor: s-resize"><img src="/graphic/face.png" /></a>';
			} else {
				vWorkersP.innerHTML = '<img src="/graphic/face.png" />';
			}
			vWorkersP.style.backgroundImage = this.CUL;
			vWorkersP.style.backgroundPosition = 'left top';
			vWorkersP.style.backgroundRepeat = 'no-repeat';
			header.appendChild(vWorkersP);
			var vWorkers = document.createElement('th');
			if (this.configGet('displayPreviewAllowSorting')) {
				vWorkers.innerHTML = '<a onclick="villagePreviewEnhancer.sortProduction(this)" style="cursor: s-resize">Zagroda</a>';
			} else {
				vWorkers.innerHTML = 'Zagroda';
			}
			vWorkers.style.backgroundImage = this.CUR;
			vWorkers.style.backgroundPosition = 'right top';
			vWorkers.style.backgroundRepeat = 'no-repeat';
			header.appendChild(vWorkers);

			if (this.configGet('displayPreviewSnobInfo')) {
				var vPack = document.createElement('th');
				if (this.configGet('displayPreviewAllowSorting')) {
					vPack.innerHTML = '<a onclick="villagePreviewEnhancer.sortProduction(this)" style="cursor: s-resize"><img src="/graphic/'+this.getWorldSetting('snobType')+'.png" /></a>';
				} else {
					vPack.innerHTML = '<img src="/graphic/'+this.getWorldSetting('snobType')+'.png" />';
				}
				vPack.style.backgroundImage = this.CUL;
				vPack.style.backgroundPosition = 'left top';
				vPack.style.backgroundRepeat = 'no-repeat';
				header.appendChild(vPack);
				var vSnob = document.createElement('th');
				if (this.configGet('displayPreviewAllowSorting')) {
					vSnob.innerHTML = '<a onclick="villagePreviewEnhancer.sortProduction(this)" style="cursor: s-resize"><img src="/graphic/unit/unit_snob.png" /></a>';
				} else {
					vSnob.innerHTML = '<img src="/graphic/unit/unit_snob.png" />';
				}
				vSnob.style.backgroundImage = this.CUR;
				vSnob.style.backgroundPosition = 'right top';
				vSnob.style.backgroundRepeat = 'no-repeat';
				header.appendChild(vSnob);
			}

			// here was Orders header section
			// moved to footer area


			for (var i=0; i<header.cells.length; i++) {
				header.cells[i].style.textAlign = 'center';
				header.cells[i].style.padding = '0px 5px';
			}

			// footer (:
			var footer = vList.insertRow(-1);
			footer.style.height = '25px';
			var fGen = document.createElement('th');
			fGen.style.backgroundImage = this.CDL;
			fGen.style.backgroundPosition = 'left bottom';
			fGen.style.backgroundRepeat = 'no-repeat';
			fGen.style.padding = '0';
			fGen.style.lineHeight = '25px';
			fGen.innerHTML = '<span style="float: left">Wyświetlanych wiosek: '+sumVillages+'</span><small class="grey" style="float: right; position: aboslute; cursor: help"><a onclick="villagePreviewEnhancer.displayAsBB()" title="Wyświetla listę wyświetlonych obecnie wiosek w formacie BB code">BB</a></small>';
			footer.appendChild(fGen);

			var fPoints = document.createElement('th');
			fPoints.style.backgroundPosition = 'right bottom';
			fPoints.style.backgroundRepeat = 'no-repeat';
			fPoints.style.backgroundImage = this.CDR;
			fPoints.style.textAlign = 'right';
			if (sumPoints > 1000000) {
				sumPoints = (sumPoints/1000000).toFixed(2)
				fPoints.innerHTML = sumPoints+'<br /><small class="grey">Mln.</small>';
			} else if (sumPoints > 1000) {
				sumPoints = (sumPoints/1000).toFixed(3);
				fPoints.innerHTML = sumPoints;
			}
			if (this.configGet('displayPreviewLoyalty')) {
				fPoints.colSpan = '2';
			}
			footer.appendChild(fPoints);

			var fWoodP = document.createElement('th');
			fWoodP.innerHTML = '<img src="/graphic/holz.png" />';
			fWoodP.style.backgroundImage = this.CDL;
			fWoodP.style.backgroundPosition = 'left bottom';
			fWoodP.style.backgroundRepeat = 'no-repeat';
			footer.appendChild(fWoodP);
			var fWood = document.createElement('th');
			if (sumWood > 1000000) {
				fWood.innerHTML = Math.round(sumWood/10000)/100+'<br /><small class="grey">Mln.</small>';
			} else {
				fWood.innerHTML = '<span style="line-height: 25px;">'+sumWood+'</span>';
			}
			fWood.style.backgroundImage = this.CDR;
			fWood.style.backgroundPosition = 'right bottom';
			fWood.style.backgroundRepeat = 'no-repeat';
			footer.appendChild(fWood);

			var fClayP = document.createElement('th');
			fClayP.innerHTML = '<img src="/graphic/lehm.png" />';
			fClayP.style.backgroundImage = this.CDL;
			fClayP.style.backgroundPosition = 'left bottom';
			fClayP.style.backgroundRepeat = 'no-repeat';
			footer.appendChild(fClayP);
			var fClay = document.createElement('th');
			if (sumClay > 1000000) {
				fClay.innerHTML = Math.round(sumClay/10000)/100+'<br /><small class="grey">Mln.</small>';
			} else {
				fClay.innerHTML = '<span style="line-height: 25px;">'+sumClay+'</span>';
			}
			fClay.style.backgroundImage = this.CDR;
			fClay.style.backgroundPosition = 'right bottom';
			fClay.style.backgroundRepeat = 'no-repeat';
			footer.appendChild(fClay);

			var fIronP = document.createElement('th');
			fIronP.innerHTML = '<img src="/graphic/eisen.png" />';
			fIronP.style.backgroundImage = this.CDL;
			fIronP.style.backgroundPosition = 'left bottom';
			fIronP.style.backgroundRepeat = 'no-repeat';
			footer.appendChild(fIronP);
			var fIron = document.createElement('th');
			if (sumIron > 1000000) {
				fIron.innerHTML = Math.round(sumIron/10000)/100+'<br /><small class="grey">Mln.</small>';
			} else {
				fIron.innerHTML = '<span style="line-height: 25px;">'+sumIron+'</span>';
			}
			fIron.style.backgroundImage = this.CDR;
			fIron.style.backgroundPosition = 'right bottom';
			fIron.style.backgroundRepeat = 'no-repeat';
			footer.appendChild(fIron);

			var fStorage = document.createElement('th');
			fStorage.style.backgroundImage = this.CDL;
			fStorage.style.backgroundPosition = 'left bottom';
			fStorage.style.backgroundRepeat = 'no-repeat';
			fStorage.colSpan = '2';
			var temp = document.createElement('div');
			temp.style.width = '100%';
			temp.style.height = '26px';
			temp.style.backgroundImage = this.CDR;
			temp.style.backgroundPosition = 'right bottom';
			temp.style.backgroundRepeat = 'no-repeat';
			temp.style.marginRight = '-5px';
			temp.style.paddingRight = '5px';
			if (sumStorage > 1000000) {
				temp.innerHTML = Math.round(sumStorage/10000)/100+'<br /><small class="grey">Mln.</small>';
			} else {
				temp.innerHTML = '<span style="line-height: 25px;">'+sumStorage+'</span>';
			}
			fStorage.appendChild(temp);
			footer.appendChild(fStorage);

			var fWorkers = document.createElement('th');
			fWorkers.style.backgroundImage = this.CDL;
			fWorkers.style.backgroundPosition = 'left bottom';
			fWorkers.style.backgroundRepeat = 'no-repeat';
			fWorkers.colSpan = '2';
			var temp = document.createElement('div');
			temp.style.width = '100%';
			temp.style.height = '26px';
			temp.style.lineHeight = '25px';
			temp.style.backgroundImage = this.CDR;
			temp.style.backgroundPosition = 'right bottom';
			temp.style.backgroundRepeat = 'no-repeat';
			temp.style.marginRight = '-5px';
			temp.style.paddingRight = '5px';
			temp.style.whiteSpace = 'nowrap';
			temp.innerHTML = Math.round(sumWorkers[0])+'<span class="grey"> / </span>'+Math.round(sumWorkers[1]);
			fWorkers.appendChild(temp);
			footer.appendChild(fWorkers);

			if (this.configGet('displayPreviewSnobInfo')) {
				var fPacks = document.createElement('th');
				fPacks.innerHTML = sumPacks;
				fPacks.style.backgroundImage = this.CDL;
				fPacks.style.backgroundPosition = 'left bottom';
				fPacks.style.backgroundRepeat = 'no-repeat';
				footer.appendChild(fPacks);
				var fSnobs = document.createElement('th');
				fSnobs.innerHTML = sumSnobs[0]+'<span class="grey">/'+sumSnobs[1]+'</span>';
				fSnobs.style.whiteSpace = 'nowrap';
				fSnobs.style.backgroundImage = this.CDR;
				fSnobs.style.backgroundPosition = 'right bottom';
				fSnobs.style.backgroundRepeat = 'no-repeat';
				footer.appendChild(fSnobs);
			}
			for (var i=0; i<footer.cells.length; i++) {
				footer.cells[i].style.textAlign = 'right';
				footer.cells[i].style.padding = '0px 5px';
				footer.cells[i].style.height = '25px';
			}
			fGen.style.textAlign = 'left';
			try {
				if (PA) {
					if ((this.configGet('displayPreviewQueueVisibility') != 'hide' || this.configGet('displayPreviewTechVisibility') != 'hide' || this.configGet('displayPreviewRecruitVisibility') != 'hide')) {
						this.log('VPE::loadProduction() => `Orders` columns are not set to hide (Q:'+this.configGet('displayPreviewQueueVisibility')+'; T:'+this.configGet('displayPreviewTechVisibility')+'; R:'+this.configGet('displayPreviewRecruitVisibility')+';)',2);
						var displayedOrdersColumns = 3;

						try {
							if ((this.configGet('displayPreviewQueueVisibility') == 'auto' && !colQueueEmpty) || this.configGet('displayPreviewQueueVisibility') == 'visible') {
								this.log('VPE::loadProduction() => Build queue column state: visible', 2);
								var vQueue = document.createElement('th');
								vQueue.innerHTML = '<a onclick="villagePreviewEnhancer.sortProduction(this, true)" style="cursor: s-resize">Budowa</a>';
								vQueue.style.textAlign = 'center';
								header.appendChild(vQueue);
							} else {
								this.log('VPE::loadProduction() => Build queue column state: hidden', 2);
								var cellIndex = navigator.appVersion.match(/MSIE 7\.0/) ? vList.rows[1].cells.length-4 : vList.rows[1].cells.length-3;
								for (var i=1; i < (vList.rows.length-1); i++) {
									vList.rows[i].deleteCell(cellIndex);
								}
								displayedOrdersColumns--;
							}
						} catch (e) {
							if (navigator.appName.match(/Microsoft Internet Explorer/)) { var ee = ''; for (var i in e) { ee += i+': '+e[i]+'; '; } e = ee; }
							this.log('VPE::loadProduction() => Error caught during Build queue column visibility evaluation :: '+e, 0);
						}

						try {
							if ((this.configGet('displayPreviewTechVisibility') == 'auto' && !colTechEmpty) || this.configGet('displayPreviewTechVisibility') == 'visible') {
								this.log('VPE::loadProduction() => Tech column state: visible', 2);
								var vTech = document.createElement('th');
								vTech.innerHTML = 'Tech.';
								vTech.style.textAlign = 'center';
								header.appendChild(vTech);
							} else {
								this.log('VPE::loadProduction() => Tech column state: hidden', 2);
								var cellIndex = navigator.appVersion.match(/MSIE 7\.0/) ? vList.rows[1].cells.length-3 : vList.rows[1].cells.length-2;
								for (var i=1; i < (vList.rows.length-1); i++) {
									vList.rows[i].deleteCell(cellIndex);
								}
								displayedOrdersColumns--;
							}
						} catch (e) {
							if (navigator.appName.match(/Microsoft Internet Explorer/)) { var ee = ''; for (var i in e) { ee += i+': '+e[i]+'; '; } e = ee; }
							this.log('VPE::loadProduction() => Error caught during Tech column visibility evaluation :: '+e, 0);
						}

						try {
							if ((this.configGet('displayPreviewRecruitVisibility') == 'auto' && !colRecruitEmpty) || this.configGet('displayPreviewRecruitVisibility') == 'visible') {
								this.log('VPE::loadProduction() => Recrutation column state: visible', 2);
								var vRecruit = document.createElement('th');
								vRecruit.innerHTML = 'Rekrutacja';
								vRecruit.style.textAlign = 'center';
								header.appendChild(vRecruit);
							} else {
								var lastRow = (vList.rows.length-1);
								this.log('VPE::loadProduction() => Recrutation column state: hidden; Attempt to remove cells from rows 1 through '+lastRow, 2);
								var cellIndex = navigator.appVersion.match(/MSIE 7\.0/) ? vList.rows[1].cells.length-2 : vList.rows[1].cells.length-1;
								for (var i=1; i < lastRow; i++) {
									try {
										this.log('VPE::loadProduction() => row('+i+').cells.length is type: '+(typeof cellIndex)+'; value: '+cellIndex, 5);
										vList.rows[i].deleteCell(cellIndex);
									} catch (e) {
										if (navigator.appName.match(/Microsoft Internet Explorer/)) { var ee = ''; for (var i2 in e) { ee += i2+': '+e[i2]+'; '; } e = ee; }
										this.log('VPE::loadProduction() => Error caught during Recruitation column removal (loop) :: attempted to remove cell: '+(vList.rows[i].cells.length-1), 0);
									}
								}
								displayedOrdersColumns--;
							}
						} catch (e) {
							if (navigator.appName.match(/Microsoft Internet Explorer/)) { var ee = ''; for (var i in e) { ee += i+': '+e[i]+'; '; } e = ee; }
							this.log('VPE::loadProduction() => Error caught during Recrutation column visibility evaluation :: '+e, 0);
						}

						try {
							if (displayedOrdersColumns > 0) {
								this.log('VPE::loadProduction() => '+displayedOrdersColumns+' columns left to display :: appendig footer', 2);
								var cellIndex = header.cells.length-displayedOrdersColumns;
								this.log('VPE::loadProduction() => left upper corner will be placed in cell: '+cellIndex, 2);
								var cell = header.cells[cellIndex];
								cell.style.backgroundImage = this.CUL;
								cell.style.backgroundPosition = 'left top';
								cell.style.backgroundRepeat = 'no-repeat';

								cell = header.cells[header.cells.length-1];
								cell.style.padding = '0px';
								var temp = document.createElement('div');
								temp.style.lineHeight = '26px';
								temp.style.backgroundImage = this.CUR;
								temp.style.backgroundPosition = 'right top';
								temp.style.backgroundRepeat = 'no-repeat';
								temp.style.marginRight = '0px';
								temp.style.paddingRight = '5px';
								temp.style.whiteSpace = 'nowrap';
								temp.innerHTML = cell.innerHTML;
								cell.innerHTML = '';
								cell.appendChild(temp);

								var fOrders = document.createElement('th');
								fOrders.style.backgroundImage = this.CDL;
								fOrders.style.backgroundPosition = 'left bottom';
								fOrders.style.backgroundRepeat = 'no-repeat';
								fOrders.style.padding = '0px';
								fOrders.style.textAlign = 'center';
								fOrders.colSpan = displayedOrdersColumns;
								var temp = document.createElement('div');
								temp.style.lineHeight = '26px';
								temp.style.backgroundImage = this.CDR;
								temp.style.backgroundPosition = 'right bottom';
								temp.style.backgroundRepeat = 'no-repeat';
								temp.style.marginRight = '0px';
								temp.style.paddingRight = '5px';
								temp.style.whiteSpace = 'nowrap';
								temp.innerHTML ='Zlecenia';
								fOrders.appendChild(temp);
								footer.appendChild(fOrders);
							}
						} catch (e) {
							if (navigator.appName.match(/Microsoft Internet Explorer/)) { var ee = ''; for (var i in e) { ee += i+': '+e[i]+'; '; } e = ee; }
							this.log('VPE::loadProduction() => Error caught during header/footer visibility evaluation :: '+e, 0);
						}
					} else {
						this.log('VPE::loadProduction() => `Orders` columns are set to hide (Q:'+this.configGet('displayPreviewQueueVisibility')+'; T:'+this.configGet('displayPreviewTechVisibility')+'; R:'+this.configGet('displayPreviewRecruitVisibility')+';)',2);
						try {
							for (var i=1; i < (vList.rows.length-1); i++) {
								vList.rows[i].deleteCell(vList.rows[i].cells.length-1);
								vList.rows[i].deleteCell(vList.rows[i].cells.length-1);
								vList.rows[i].deleteCell(vList.rows[i].cells.length-1);
							}
						} catch (e) {
							this.log('VPE::loadProduction() => failed cells removal', 3);
						}
					}
				}
			} catch (e) {
				if (navigator.appName.match(/Microsoft Internet Explorer/)) { var ee = ''; for (var i in e) { ee += i+': '+e[i]+'; '; } e = ee; }
				this.log('VPE::loadProduction() => Error caught during `Orders` columns visibility evaluation :: '+e, 0);
			}
			this.log('VPE::loadProdcution() => rows[1].cells.length: '+vList.rows[1].cells.length, 2);
		} catch (e) {
			if (navigator.appName.match(/Microsoft Internet Explorer/)) { var ee = ''; for (var i in e) { ee += i+': '+e[i]+'; '; } e = ee; }
			this.log('VPE::loadProduction() => '+e, 0);
		}
	},

	sortProduction : function (obj, lookInAbbrTag) {
		try {
			if ((typeof lookInNameTag) == "undefined") {
				lookInNameTag = false;
			}


			var colIndex = 0;
			if (this.configGet('displayPreviewLoyalty')) { colIndex += 1 }
			if (this.configGet('displayPreviewPercentResources')) { colIndex += 2}
			if (this.configGet('displayPreviewPercentWorkers')) { colIndex += 4}

			var colTranslate = [[ 0, 1, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9,10], // 000 - all hidden
								[ 0, 1, 2, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9,10,11], // 001 - loyalty shown
								[ 0, 1, 3, 4, 5, 6, 7, 8, 9, 9,10,10,11,12,13], // 010 - % resources shown
								[ 0, 1, 2, 4, 5, 6, 7, 8, 9,10,10,11,11,12,13,14], // 011
								[ 0, 1, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8, 9,10,11], // 100 - % workers shown
								[ 0, 1, 2, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9,10,11,12], // 101
								[ 0, 1, 3, 4, 5, 6, 7, 8, 9, 9,10,11,12,13,14], // 110
								[ 0, 1, 2, 4, 5, 6, 7, 8, 9,10,10,11,12,13,14,15], // 111 - all shown
							   ];

			colIndex = colTranslate[colIndex][obj.parentNode.cellIndex];
			var vList = obj.parentNode.parentNode.parentNode;
			if (vList.rows.length == 3) {
				this.log('VPE::sortProduction() => cellIndex: '+colIndex+'; sorting request ignored :: only one row', 1);
				return false;
			}
			var lastRow = vList.rows.length-2;
			if (!this.isPA()) {
				this.log('VPE::sortProduction() => cellIndex: '+colIndex+'; lastRow: '+lastRow+'; sorting request ignored :: PA NOT detected', 1);
				return false;
			}
			if (this.sortingInProgress) {
				this.log('VPE::sortProduction() => cellIndex: '+colIndex+'; lastRow: '+lastRow+'; sorting request ignored :: another sorting process is running', 1);
				return false;
			}
			this.sortingInProgress = true;
			this.log('VPE::sortProduction() => cellIndex: '+colIndex+'; lastRow: '+lastRow+';', 1);
			var currentRow = 1;
			var iterationCount = 1;
			var row1, row2, vRow1, vRow2, vName1, vName2;
			var sortingOrder = 'a';

			// construct array to process
			var arrayToSort = new Array();
			for (var i=0; i<lastRow; i++)  {
				if (colIndex == 0) {
					arrayToSort.push(vList.rows[i+1].id+',"'+vList.rows[i+1].cells[colIndex].innerHTML.replace(/<.*?>/g,'').replace(/^(\r|\n|\t|[ ])+|((\r|\n|\t|[ ])+)$/g,'').toLowerCase()+'"');
				} else {
					if (lookInAbbrTag) {
						arrayToSort.push(vList.rows[i+1].id + ',' + parseFloat(vList.rows[i+1].cells[colIndex].abbr) + ',"' + vList.rows[i+1].cells[0].innerHTML.replace(/<.*?>/g,'').replace(/^(\r|\n|\t|[ ])+|((\r|\n|\t|[ ])+)$/g,'').toLowerCase()+'"');
					} else {
						arrayToSort.push(vList.rows[i+1].id + ',' + parseFloat(vList.rows[i+1].cells[colIndex].innerHTML.replace(/<.*?>/g,'')) + ',"' + vList.rows[i+1].cells[0].innerHTML.replace(/<.*?>/g,'').replace(/^(\r|\n|\t|[ ])+|((\r|\n|\t|[ ])+)$/g,'').toLowerCase()+'"');
					}
				}
			}
			this.log('VPE::sortProduction() => initial array: <pre>'+arrayToSort.join('\n')+'</pre>', 4);
			if (this.sortedBy.split(',')[0] == colIndex && this.sortedBy.split(',')[1] == 'a') {
				this.log('VPE::sortProduction() => sorted array: <pre>'+arrayToSort.sort(this.sortDESC).join('\n')+'</pre>', 4);
				//arrayToSort.reverse();
				this.sortedBy = colIndex+',d';
			} else if (this.sortedBy.split(',')[0] != colIndex) {
				this.log('VPE::sortProduction() => sorted array: <pre>'+arrayToSort.sort(this.sortASC).join('\n')+'</pre>', 4);
				this.sortedBy = colIndex+',a';
			} else {
				this.log('VPE::sortProduction() => sorted array: <pre>'+arrayToSort.sort(this.sortASC).join('\n')+'</pre>', 4);
				this.sortedBy = colIndex+',a';
			}
			for (var i=0; i<arrayToSort.length; i++) {
				vList.insertBefore(document.getElementById(arrayToSort[i].split(',')[0]), vList.rows[1]);
			}
			for (currentRow=1; currentRow <= lastRow; currentRow++) {
				vList.rows[currentRow].className = 'nowrap '+(currentRow%2 ? 'row_a' : 'row_b');
			}

			this.log('VPE::sortProduction() => sorting finished :: sorted by: `'+this.sortedBy+'`;', 1);

			this.sortingInProgress = false;
		} catch (e) {
			this.log('VPE::sortProduction() => Error caught: '+e, 0);
		}
	},

	displayAsBB : function () {
		try {
			var vList = document.getElementById('village_list');
			var firstRow = 1;
			var lastRow = vList.rows.length-2;
			var BBData = new Array();
			var PlainTextData = new Array();
			for (var i=firstRow; i<=lastRow; i++) {
				PlainTextData.push(vList.rows[i].cells[0].innerHTML.replace(/(<.*?>)|\r|\n|\t/g,''));
				BBData.push(vList.rows[i].cells[0].abbr);
			}
			this.log('VPE::displayAsBB() => <pre>\n'+BBData.join(';\n'), 1);
			var tables = document.getElementsByTagName('table');
			if (document.getElementById('villages_plaintext') == null) {
				var plaintext = document.createElement('pre');
				plaintext.style.cssFloat = 'left';
				plaintext.style.marginLeft = '10px';
				plaintext.id = 'villages_plaintext';
			} else {
				var plaintext = document.getElementById('villages_plaintext');
			}
			if (document.getElementById('villages_bblist') == null) {
				var bblist = document.createElement('pre');
				bblist.style.cssFloat = 'left';
				bblist.style.marginRight = '10px';
				bblist.id = 'villages_bblist';
			} else {
				var bblist = document.getElementById('villages_bblist');
			}
			bblist.innerHTML = '[village]'+BBData.join('[/village]<br />[village]')+'[/village]';
			plaintext.innerHTML = PlainTextData.join('<br />')
			tables[tables.length-1].appendChild(plaintext);
			tables[tables.length-1].appendChild(bblist);
		} catch (e) {
			this.log('VPE::displayAsBB() => Error caught: '+e);
		}
	},


	// ---------------------------------------------------------------------------------------
	//
	// background workers
	//
	// ---------------------------------------------------------------------------------------

	headerUpdater : function () {
		this.headerWoodUpdater();
		this.headerClayUpdater();
		this.headerIronUpdater();
	},

	flashWorkersOverfill : function (cellId) {
		try {
			var cell = document.getElementById(cellId);
			this.log('VPE::flashWorkersOverfill() => flashing: '+cellId+' background is: '+cell.style.backgroundColor, 4);
			if (cell.style.backgroundColor == this.standardColorPalette[100]) {
				cell.style.backgroundColor = 'transparent';
				cell.style.color = '#000000';
			} else {
				cell.style.backgroundColor = this.standardColorPalette[100];
				cell.style.color = '#FFFFFF';
			}
		} catch (e) {
			this.log('VPE::flashWorkersOverfill() => '+e, 1);
		}
	},


	// ---------------------------------------------------------------------------------------
	//
	// data colectors
	//
	// ---------------------------------------------------------------------------------------

	loyaltyScan : function () {
		try {
			var tables = document.getElementsByTagName('table');
			var villageId = this.getVillageId();
			var scanTime = parseInt(parseInt(parseInt(new Date().getTime()/1000)/60)/60);
			var loyalty = null;
			for (var i=0; i< tables.length; i++) {
				if (tables[i].className == 'vis' && tables[i].rows.length == 1 && tables[i].rows[0].getElementsByTagName('th').length == 2) {
					loyalty = parseInt(tables[i].rows[0].getElementsByTagName('th')[1].innerHTML);
					this.log('VPE::loyaltyScan() => loyalty found: '+villageId+' :: '+(scanTime)+' :: '+loyalty, 1);
					break;
				}
			}
			if (loyalty == null) {
				loyalty = 100;
				this.log('VPE::loyaltyScan() => no loyalty table found, setting to: '+villageId+' :: '+(scanTime)+' :: '+loyalty, 1);
			}

			this.setLoyalty(villageId, loyalty, scanTime);

			return true;
		} catch (e) {
			this.log(e, 0);
		}
	},
	getWorld : function () {
		return document.URL.match(/pl(\d+)/)[1];
	},
	getWorldId : function () {
		return document.URL.match(/pl(c)?(\d+)/)[0];
	},
	getURL : function () {
		this.log('VPE::getURL() => '+document.URL.match(/php\?(.*)/)[1], 1);
		return document.URL.match(/php\?(.*)/)[1];
	},
	getWood : function () {
		return parseInt(document.getElementById('wood').innerHTML);
	},
	getClay : function () {
		return parseInt(document.getElementById('stone').innerHTML);
	},
	getIron : function () {
		return parseInt(document.getElementById('iron').innerHTML);
	},
	getStorage : function () {
		return parseInt(document.getElementById('storage').innerHTML);
	},
	getWorkers : function () {
		var tables = document.getElementsByTagName('table');
		for (var i=0; i<tables.length; i++) {
			if (tables[i].className == 'navi-border' && tables[i].rows.length == 1 && tables[i].innerHTML.match(/face\.png/)) {
				workers = tables[i].rows[0].cells[0].getElementsByTagName('table')[0].rows[0].cells[1].innerHTML.match(/(\d+)\/(\d+)/);
				return { current : workers[1], limit : workers[2] };
			}
		}
	},
	getVillageId : function () {
		//return this.getURL().match(/village=(\d+)/)[1];
		var tables = document.getElementsByTagName('table');
		for (var i=0; i<tables.length; i++) {
			if (tables[i].innerHTML.match(/game.php\?village=(\d+)&amp;screen=overview_villages/)) {
				return tables[i].innerHTML.match(/game.php\?village=(\d+)&amp;screen=overview_villages/)[1];
			}
		}
	},
	getOverviewMode : function () {
		if (document.getElementById('overview') == null) {
			return false;
		} else {
			return document.getElementById('overview').value;
		}
	},
	isPA : function () {
		var tables = document.getElementsByTagName('table');
		for (var i=0; i<tables.length; i++) {
			if (tables[i].rows[0].id == 'menu_row2' && tables[i].rows[0].cells.length == 5 && tables[i].rows[0].cells[4].innerHTML.match(/villages.png/)) {
				this.log('VPE::isPA() => PA detected', 2);
				return true;
			}
		}
		this.log('VPE::isPA() => PA NOT detected', 2);
		return false;
	},




	// ---------------------------------------------------------------------------------------
	//
	// raw cookie parsers
	//
	// ---------------------------------------------------------------------------------------

	setValue : function (name, value) {
		try {
			document.cookie = name + '=' + escape(value) + '; expires=' + (new Date(2020, 12, 1)).toGMTString() + ';';
		} catch (e) {
			this.log(e, 0);
		}
	},
	getValue : function (name) {
		eval('var reg = /'+name+'=(.*?)(?:;|$)/;');
		var value = document.cookie.match(reg);
		if (value) {
			var ret;
			switch (unescape(value[1])) {
				case 'true':
					ret = true;
					break;
				case 'false':
					ret = false;
					break;
				default:
					ret = unescape(value[1]);
			}
			return ret;
		}
		return null;
	},


	// ---------------------------------------------------------------------------------------
	//
	// cookie helpers
	//
	// ---------------------------------------------------------------------------------------

	setLoyalty : function (villageId, loyalty, scanTime) {
		var data = this.getValue('VPE_LoyaltyData_'+this.getWorld());
		if (data != null) {
			eval("var reg = /"+villageId+",.*?,.*?(?:[|]|$)/;");
			if (data.match(reg)) {
				this.log('VPE::setLoyalty() => '+villageId+' loyalty was stored :: match is: `'+data.match(reg)+'`', 1);
				data = data.replace(reg,villageId+','+scanTime+','+loyalty+'|');
			} else {
				this.log('VPE::setLoyalty() => '+villageId+' loyalty was NOT stored :: search_patt: `'+reg+'`', 1);
				data = data.replace(/\|$/,'')+'|'+villageId+','+scanTime+','+loyalty;
			}
			this.log('VPE::setLoyalty() => current data: '+data, 2);
		} else {
			this.log('VPE::setLoyalty() => no loyalty data was stored', 1);
			data = villageId+','+scanTime+','+loyalty;
		}
		this.setValue('VPE_LoyaltyData_'+this.getWorld(), data);
	},

	getLoyalty : function (villageId) {
		var data = this.getValue('VPE_LoyaltyData_'+this.getWorld());
		if (data != null) {
			var reg = new RegExp(villageId+",(.*?),(.*?)(?:[|]|$)");
			if (reg.test(data)) {
				this.log('VPE::getLoyalty() => got loyalty for: '+villageId+' :: '+data.match(reg)[1]+','+data.match(reg)[2], 3);
				return data.match(reg)[1]+','+data.match(reg)[2];
			} else {
				this.log('VPE::getLoyalty() => no loyalty stored for: '+villageId, 3);
				return null;
			}
		} else {
			this.log('VPE::getLoyalty() => data read null', 1);
			return null;
		}
		return null;
	},

	loadConfigData : function () {
		if (!this.configLoaded) {
			var new_settings = this.getValue('VPE_Settings_'+this.getWorld());
			this.log('VPE::loadConfigData() => ('+(typeof new_settings)+') '+new_settings, 1);
			if (new_settings != null) {
				this.log('VPE::loadConfigData() => '+new_settings, 1);
				new_settings = new_settings.split('|');
				for (var i=0; i<new_settings.length; i++) {
					var setting = new_settings[i].split(',');
					switch (setting[1]) {
						case 'true':
							setting[1] = true;
							break;
						case 'false':
							setting[1] = false;
							break;
					}
					this.settings[setting[0]] = setting[1];
				}
				this.settingsEmpty = false;
			} else {
				this.settingsEmpty = true;
			}
			this.configLoaded=true;
		}
	},

	storeSettings : function () {
		try {
			var sForm = document.forms[0].elements;
			this.log('VPE::storeSettings() => '+(sForm.length), 2);

			var displayPreviewResourcesAlertTreshold = parseInt(document.getElementById('displayPreviewResourcesAlertTreshold').value);
			if (document.getElementById('displayPreviewResourcesAlert').checked && (displayPreviewResourcesAlertTreshold < 5 || displayPreviewResourcesAlertTreshold > 90)) {
				this.log('VPE::storeSettings() => displayPreviewResourcesAlertTreshold :: validation ERROR', 2)
				alert('Wprowadzono nieprawidłową wartość w polu "Oznaczaj spadek surowców poniżej %".\nWartość powinna znajdować się w przedziale 5-90.');
				return false;
			} else {
				if (document.getElementById('displayPreviewResourcesAlertMarkTypeColor').checked && !document.getElementById('displayPreviewResourcesAlertMarkValueColor').value.match(/^[0-9ABCDEF]{6}$/i)) {
					alert('Wprowadzono nieprawidłową wartość w polu "Kolor w formacie hexadecymalnym".');
					return false;
				}
				if (document.getElementById('displayPreviewResourcesAlert').checked && !document.getElementById('displayPreviewResourcesAlertMarkTypeColor').checked && !document.getElementById('displayPreviewResourcesAlertMarkTypeDynamic').checked) {
					alert('Nie wybrano formatu oznaczania niskiego stanu surowców');
					return false;
				}

				this.log('VPE::storeSettings() => displayPreviewResourcesAlertTreshold :: validation OK', 2)
			}
			if (document.getElementById('displayPreviewFullWorkersNeutralization').checked) {
				if (!document.getElementById('displayPreviewFullWorkersNeutralizationTreshold').value.match(/^\d{1,5}$/)) {
					alert('Wprowadzono nieprawidłową wartość w polu "Ilość wolnych miejsc poniżej której zmienić podświetlenie".');
					return false;
				}
				if (document.getElementById('displayPreviewFullWorkersNeutralizationMarkTypeColor').checked && !document.getElementById('displayPreviewFullWorkersNeutralizationMarkValueColor').value.match(/^[0-9ABCDEF]{6}$/i)) {
					alert('Wprowadzono nieprawidłową wartość w polu "Kolor w formacie hexadecymalnym".');
					return false;
				} else if (
					document.getElementById('displayPreviewFullWorkersNeutralizationMarkTypePercent').checked && (!document.getElementById('displayPreviewFullWorkersNeutralizationMarkValuePercent').value.match(/^\d{1,3}$/) || parseInt(document.getElementById('displayPreviewFullWorkersNeutralizationMarkValuePercent').value) > 100)) {
					alert('Wprowadzono nieprawidłową wartość w polu "Kolor z palety kolorów z podświetlania zagrody".');
					return false;
				}
				if (!document.getElementById('displayPreviewFullWorkersNeutralizationMarkTypeColor').checked && !document.getElementById('displayPreviewFullWorkersNeutralizationMarkTypePercent').checked) {
					alert('Nie wybrano formatu oznaczania zapełnienia zagrody');
					return false;
				}
			}

			if (document.getElementById('displayPreviewWorkersFlashOnOverfill').checked && !document.getElementById('displayPreviewWorkersFlashOnOverfillDelay').value.match(/^\d+$/)) {
				alert('Wprowadzono nieprawidłowy interwał zmiany stanu przy mruganiu przepełnienia zagrody');
				return false;
			}


			var new_settings = new Array();
			for (var i=0; i<sForm.length; i++) {
				this.log('VPE::storeSettings() => formElement['+i+']; name: ('+(typeof sForm[i].name)+')`'+sForm[i].name+'`, id: `'+sForm[i].id+'`, value: `'+sForm[i].value+'`', 3);
				if (sForm[i].name != '') {
					if (sForm[i].value == '') {
						sForm[i].value = '';
					}
					if (sForm[i].value == 'NaN') {
						sForm[i].value = 0;
					}
					if (sForm[i].type == 'checkbox' || sForm[i].type == 'radio') {
						sForm[i].value = sForm[i].checked;
					}
					new_settings.push(sForm[i].id+','+sForm[i].value);
				}
			}
			new_settings = new_settings.join('|');
			this.log('VPE::storeSettings() => new_settings: '+new_settings, 1);
			this.setValue('VPE_Settings_'+this.getWorld(), new_settings);
			document.location.reload();
		} catch (e) {
			this.log('VPE::storeSettings() => '+e, 0);
			return false;
		}
		return false;
	},




	// ---------------------------------------------------------------------------------------
	//
	// helpers
	//
	// ---------------------------------------------------------------------------------------

	calcPack : function (wood, clay, iron) {
		var pack = Math.floor(Math.min(wood/this.getWorldSetting('packPrice')[0], (Math.min(clay/this.getWorldSetting('packPrice')[1], iron/this.getWorldSetting('packPrice')[2]))));
		return pack;
	},

	calcSnob : function (wood, clay, iron, workers) {
		var snob = new Array();
		snob[0] = Math.floor(Math.min((workers)/100, Math.min(wood/this.getWorldSetting('snobPrice')[0], (Math.min(clay/this.getWorldSetting('snobPrice')[1], iron/this.getWorldSetting('snobPrice')[2])))));
		snob[1] = Math.floor(Math.min(wood/this.getWorldSetting('snobPrice')[0], (Math.min(clay/this.getWorldSetting('snobPrice')[1], iron/this.getWorldSetting('snobPrice')[2]))));
		return snob;
	},

	configGet : function (setting) {
		this.loadConfigData();
		if (!this.settingsEmpty) {
			if (setting == 'displayPreviewWorkersFlashOnOverfillDelay' && isNaN(parseInt(this.settings[setting]))) {
				return 1;
			}
			if ((typeof this.settings[setting]) == 'undefined') {
				return '';
			} else {
				return this.settings[setting];
			}
		} else {
			return '';
		}
	},
	configFormWorkersNeutralizationActivator : function (obj) {
		this.log('VPE::configFormWorkersNeutralizationActivator() => called with: '+obj, 2);
		var active=obj;
		document.getElementById('displayPreviewFullWorkersNeutralizationTreshold').disabled=!active;
		document.getElementById('displayPreviewFullWorkersNeutralizationMarkTypePercent').disabled=!active;
		document.getElementById('displayPreviewFullWorkersNeutralizationMarkValuePercent').disabled=!active;
		document.getElementById('displayPreviewFullWorkersNeutralizationMarkTypeColor').disabled=!active;
		document.getElementById('displayPreviewFullWorkersNeutralizationMarkValueColor').disabled=!active;
	},

	getWorldSetting : function (setting) {
	     var world = this.getWorldId().replace("pl","");
	     world = world.replace("c1","0");
	     world = parseInt(world);

	     var worldset = this.worldSettings.worldset;
	     if(setting == "snobType"){
	          return this.worldSettings.snobType[worldset[world][0]];
	     }
	     else if(setting == "packPrice"){
	          return this.worldSettings.packPrice[worldset[world][1]];
	     }
	     else if(setting == "snobPrice"){
	          return this.worldSettings.snobPrice[worldset[world][2]];
	     }
	     else if(setting == "loyaltyPerHour"){
	          return this.worldSettings.loyaltyPerHour[worldset[world][3]];
	     }
	},

	parseFinishTime : function (input) {
		try {
			output = input.split(' ');
			switch (output[0]) {
				case 'dziś':
					output = new Date(
						new Date().getFullYear(),
						new Date().getMonth(),
						new Date().getDate(),
						output[2].split(':')[0],
						output[2].split(':')[1]
					);
					output = (parseInt(output.getTime()/1000));
					break;
				case 'jutro':
					output = new Date(
						new Date().getFullYear(),
						new Date().getMonth(),
						new Date().getDate()+1,
						output[2].split(':')[0],
						output[2].split(':')[1]
					);
					output = (parseInt(output.getTime()/1000));
					break;
				case 'dnia':
					output = new Date(
						(output[1].split('.')[1]-1 < new Date().getMonth() ? new Date().getFullYear()+1 : new Date().getFullYear()),
						output[1].split('.')[1]-1,
						output[1].split('.')[0],
						output[3].split(':')[0],
						output[3].split(':')[1]
					);
					output = (parseInt(output.getTime()/1000))
					break;
				default:
					output = '?????? '+output;

			}
			this.log('VPE::parseFinishTime() => input: `'+input+'` output: '+output, 3);
			output = isFinite(output) ? output : 0;
			return output;
		} catch (e) {
			this.log('VPE::parseFinishTime() => Error caught: '+e, 0);
		}
	},



	// ---------------------------------------------------------------------------------------
	//
	// used internaly by JS
	//
	// ---------------------------------------------------------------------------------------

	sortASC : function(a, b) {
		var valsA = a.split(",");
		var valsB = b.split(",");

		if (valsA.length == 3) {
			valsA[1] = parseFloat(valsA[1]);
			valsB[1] = parseFloat(valsB[1]);
		}
		if (valsA[1] > valsB[1]) {
			return -1;
		} else if (valsA[1] == valsB[1] && valsA.length == 3 && valsA[2] > valsB[2]) {
			return -1;
		} else {
			return 1;
		}
	},
	sortDESC : function(a, b) {
		var valsA = a.split(",");
		var valsB = b.split(",");

		if (valsA.length == 3) {
			valsA[1] = parseFloat(valsA[1]);
			valsB[1] = parseFloat(valsB[1]);
		}
		if (valsA[1] > valsB[1]) {
			return 1;
		} else if (valsA[1] == valsB[1] && valsA.length == 3 && valsA[2] < valsB[2]) {
			return 1;
		} else {
			return -1;
		}
	},

// ---------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------



	fillResourcesAlertColorTable : function () {
		if (!this.resourcesAlertColorPaletteFilled) {
			this.log('VPE::fillResourcesAlertColorTable()', 1);
			try {
				var treshold = parseInt(this.configGet('displayPreviewResourcesAlertTreshold'));
				if (isNaN(treshold) || treshold < 5 || treshold > 90) {
					treshold = 0;
					return;
				}
				var steps = treshold+1;
				if (this.configGet("useColorBlindPalette")) {
					var step = Math.round(255/steps)-1;
					var colorR = 255;
					var colorG = 255;
					var colorB = 0;

					for(var c=0; c<=steps; c++) {
						var farbeR = (colorR - step * c).toString(16);
						var farbeG = (colorG - step * c).toString(16);
						var farbeB = (colorB + step * c).toString(16);

						if(farbeR.length == 1) {
							farbeR = "0" + farbeR;
						}
						if(farbeG.length == 1) {
							farbeG = "0" + farbeG;
						}
						if(farbeB.length == 1) {
							farbeB = "0" + farbeB;
						}

						this.resourcesAlertColorPalette[c] = "#" + farbeR + farbeG + farbeB;
					}
				} else {
					var step = Math.round(255/steps)-1;
					var colorR = 0;
					var colorG = 255;
					var colorB = 0;

					for(c=0; c<=steps; c++) {
						var farbeR = "00"
						var farbeG = (colorG - step * c).toString(16);
						var farbeB = (colorR + step * c).toString(16);

						if(farbeR.length == 1) {
							farbeR = "0" + farbeR;
						}
						if(farbeG.length == 1) {
							farbeG = "0" + farbeG;
						}
						if(farbeB.length == 1) {
							farbeB = "0" + farbeB;
						}

						this.resourcesAlertColorPalette[c] = "#" + farbeR + farbeG + farbeB;
					}
				}
				this.resourcesAlertColorPaletteFilled = true;
			} catch (e) {
				this.log(e, 0);
			}
		}
	},

	fillResourcesColorTable : function () {
		if (!this.resourcesColorPaletteFilled) {
			this.log('VPE::fillResourcesColorTable()', 1);
			try {
				if (this.configGet('displayPreviewResourcesAlert')) {
					var treshold = parseInt(this.configGet('displayPreviewResourcesAlertTreshold'));
					if (isNaN(treshold) || treshold < 5 || treshold > 90) {
						treshold = 0;
					}
				} else {
					var treshold = 0;
				}
				var steps = 100-treshold;
				var step = Math.round(255/steps)-1;
				if (this.configGet("useColorBlindPalette")) {
					var colorR = 255;
					var colorG = 255;
					var colorB = 0;

					for(var c=0; c<=steps; c++) {
						var farbeR = (colorR - step * c).toString(16);
						var farbeG = (colorG - step * c).toString(16);
						var farbeB = (colorB + step * c).toString(16);

						if(farbeR.length == 1) {
							farbeR = "0" + farbeR;
						}
						if(farbeG.length == 1) {
							farbeG = "0" + farbeG;
						}
						if(farbeB.length == 1) {
							farbeB = "0" + farbeB;
						}

						this.resourcesColorPalette[c] = "#" + farbeR + farbeG + farbeB;
					}
				} else {
					var colorR = 0;
					var colorG = 255;
					var colorB = 255;

					for(c=0; c<=steps; c++) {
						var farbeR = (colorR + step * c).toString(16);
						var farbeG = (colorG - step * c).toString(16);
						var farbeB = "00"

						if(farbeR.length == 1) {
							farbeR = "0" + farbeR;
						}
						if(farbeG.length == 1) {
							farbeG = "0" + farbeG;
						}

						this.resourcesColorPalette[c] = "#" + farbeR + farbeG + farbeB;
					}
				}
				this.resourcesColorPaletteFilled = true;
			} catch (e) {
				this.log(e, 0);
			}
		}
	},

	fillStandardColorTable : function () {
		if (!this.standardColorPaletteFilled) {
			this.log('VPE::fillStandardColorTable()', 1);
			try {
				var steps = 100;
				if (this.configGet("useColorBlindPalette")) {
					var step = Math.round(255/steps)-1;
					var colorR = 255;
					var colorG = 255;
					var colorB = 0;

					for(var c=0; c<=steps; c++) {
						var farbeR = (colorR - step * c).toString(16);
						var farbeG = (colorG - step * c).toString(16);
						var farbeB = (colorB + step * c).toString(16);

						if(farbeR.length == 1) {
							farbeR = "0" + farbeR;
						}
						if(farbeG.length == 1) {
							farbeG = "0" + farbeG;
						}
						if(farbeB.length == 1) {
							farbeB = "0" + farbeB;
						}

						this.standardColorPalette[c] = "#" + farbeR + farbeG + farbeB;
					}
				} else {
					var step = Math.round(255/steps)-1;
					var colorR = 0;
					var colorG = 255;
					var colorB = 255;


					for(c=0; c<=steps; c++) {
						var farbeR = (colorR + step * c).toString(16);
						var farbeG = (colorG - step * c).toString(16);
						var farbeB = "00"

						if(farbeR.length == 1) {
							farbeR = "0" + farbeR;
						}
						if(farbeG.length == 1) {
							farbeG = "0" + farbeG;
						}

						this.standardColorPalette[c] = "#" + farbeR + farbeG + farbeB;
					}
				}
				this.standardColorPaletteFilled = true;
			} catch (e) {
				this.log(e, 0);
			}
		}
	}



};

unsafeWindow.villagePreviewEnhancer.init();
